home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / main / http_core.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-07  |  84.5 KB  |  2,936 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1995-1999 The Apache Group.  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 Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" 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 Group.
  29.  *
  30.  * 6. Redistributions of any form whatsoever must retain the following
  31.  *    acknowledgment:
  32.  *    "This product includes software developed by the Apache Group
  33.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group 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 Group and the Apache HTTP server
  54.  * project, please see <http://www.apache.org/>.
  55.  *
  56.  */
  57.  
  58. #define CORE_PRIVATE
  59. #include "httpd.h"
  60. #include "http_config.h"
  61. #include "http_core.h"
  62. #include "http_protocol.h"    /* For index_of_response().  Grump. */
  63. #include "http_request.h"
  64. #include "http_conf_globals.h"
  65. #include "http_vhost.h"
  66. #include "http_main.h"        /* For the default_handler below... */
  67. #include "http_log.h"
  68. #include "rfc1413.h"
  69. #include "util_md5.h"
  70. #include "scoreboard.h"
  71. #include "fnmatch.h"
  72.  
  73. #ifdef USE_MMAP_FILES
  74. #include <sys/mman.h>
  75.  
  76. /* mmap support for static files based on ideas from John Heidemann's
  77.  * patch against 1.0.5.  See
  78.  * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
  79.  */
  80.  
  81. /* Files have to be at least this big before they're mmap()d.  This is to deal
  82.  * with systems where the expense of doing an mmap() and an munmap() outweighs
  83.  * the benefit for small files.  It shouldn't be set lower than 1.
  84.  */
  85. #ifndef MMAP_THRESHOLD
  86. #ifdef SUNOS4
  87. #define MMAP_THRESHOLD        (8*1024)
  88. #else
  89. #define MMAP_THRESHOLD        1
  90. #endif
  91. #endif
  92. #endif
  93.  
  94. /* Server core module... This module provides support for really basic
  95.  * server operations, including options and commands which control the
  96.  * operation of other modules.  Consider this the bureaucracy module.
  97.  *
  98.  * The core module also defines handlers, etc., do handle just enough
  99.  * to allow a server with the core module ONLY to actually serve documents
  100.  * (though it slaps DefaultType on all of 'em); this was useful in testing,
  101.  * but may not be worth preserving.
  102.  *
  103.  * This file could almost be mod_core.c, except for the stuff which affects
  104.  * the http_conf_globals.
  105.  */
  106.  
  107. static void *create_core_dir_config(pool *a, char *dir)
  108. {
  109.     core_dir_config *conf;
  110.  
  111.     conf = (core_dir_config *)ap_pcalloc(a, sizeof(core_dir_config));
  112.     if (!dir || dir[strlen(dir) - 1] == '/') {
  113.         conf->d = dir;
  114.     }
  115.     else if (strncmp(dir, "proxy:", 6) == 0) {
  116.         conf->d = ap_pstrdup(a, dir);
  117.     }
  118.     else {
  119.         conf->d = ap_pstrcat(a, dir, "/", NULL);
  120.     }
  121.     conf->d_is_fnmatch = conf->d ? (ap_is_fnmatch(conf->d) != 0) : 0;
  122.     conf->d_components = conf->d ? ap_count_dirs(conf->d) : 0;
  123.  
  124.     conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
  125.     conf->opts_add = conf->opts_remove = OPT_NONE;
  126.     conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
  127.  
  128.     conf->content_md5 = 2;
  129.  
  130.     conf->use_canonical_name = 1 | 2;    /* 2 = unset, default on */
  131.  
  132.     conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
  133.     conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */
  134.     conf->satisfy = SATISFY_NOSPEC;
  135.  
  136. #ifdef RLIMIT_CPU
  137.     conf->limit_cpu = NULL;
  138. #endif
  139. #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
  140.     conf->limit_mem = NULL;
  141. #endif
  142. #ifdef RLIMIT_NPROC
  143.     conf->limit_nproc = NULL;
  144. #endif
  145.  
  146.     conf->limit_req_body = 0;
  147.     conf->sec = ap_make_array(a, 2, sizeof(void *));
  148.  
  149.     return (void *)conf;
  150. }
  151.  
  152. static void *merge_core_dir_configs(pool *a, void *basev, void *newv)
  153. {
  154.     core_dir_config *base = (core_dir_config *)basev;
  155.     core_dir_config *new = (core_dir_config *)newv;
  156.     core_dir_config *conf;
  157.     int i;
  158.   
  159.     conf = (core_dir_config *)ap_palloc(a, sizeof(core_dir_config));
  160.     memcpy((char *)conf, (const char *)base, sizeof(core_dir_config));
  161.     if (base->response_code_strings) {
  162.     conf->response_code_strings =
  163.         ap_palloc(a, sizeof(*conf->response_code_strings)
  164.               * RESPONSE_CODES);
  165.     memcpy(conf->response_code_strings, base->response_code_strings,
  166.            sizeof(*conf->response_code_strings) * RESPONSE_CODES);
  167.     }
  168.     
  169.     conf->d = new->d;
  170.     conf->d_is_fnmatch = new->d_is_fnmatch;
  171.     conf->d_components = new->d_components;
  172.     conf->r = new->r;
  173.     
  174.     if (new->opts & OPT_UNSET) {
  175.     /* there was no explicit setting of new->opts, so we merge
  176.      * preserve the invariant (opts_add & opts_remove) == 0
  177.      */
  178.     conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
  179.     conf->opts_remove = (conf->opts_remove & ~new->opts_add)
  180.                         | new->opts_remove;
  181.     conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
  182.         if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
  183.             conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
  184.     }
  185.     }
  186.     else {
  187.     /* otherwise we just copy, because an explicit opts setting
  188.      * overrides all earlier +/- modifiers
  189.      */
  190.     conf->opts = new->opts;
  191.     conf->opts_add = new->opts_add;
  192.     conf->opts_remove = new->opts_remove;
  193.     }
  194.  
  195.     if (!(new->override & OR_UNSET)) {
  196.         conf->override = new->override;
  197.     }
  198.     if (new->ap_default_type) {
  199.         conf->ap_default_type = new->ap_default_type;
  200.     }
  201.     
  202.     if (new->ap_auth_type) {
  203.         conf->ap_auth_type = new->ap_auth_type;
  204.     }
  205.     if (new->ap_auth_name) {
  206.         conf->ap_auth_name = new->ap_auth_name;
  207.     }
  208.     if (new->ap_requires) {
  209.         conf->ap_requires = new->ap_requires;
  210.     }
  211.  
  212.     if (new->response_code_strings) {
  213.     if (conf->response_code_strings == NULL) {
  214.         conf->response_code_strings = ap_palloc(a,
  215.         sizeof(*conf->response_code_strings) * RESPONSE_CODES);
  216.         memcpy(conf->response_code_strings, new->response_code_strings,
  217.            sizeof(*conf->response_code_strings) * RESPONSE_CODES);
  218.     }
  219.     else {
  220.         for (i = 0; i < RESPONSE_CODES; ++i) {
  221.             if (new->response_code_strings[i] != NULL) {
  222.             conf->response_code_strings[i]
  223.                 = new->response_code_strings[i];
  224.         }
  225.         }
  226.     }
  227.     }
  228.     if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
  229.     conf->hostname_lookups = new->hostname_lookups;
  230.     }
  231.     if ((new->do_rfc1413 & 2) == 0) {
  232.         conf->do_rfc1413 = new->do_rfc1413;
  233.     }
  234.     if ((new->content_md5 & 2) == 0) {
  235.         conf->content_md5 = new->content_md5;
  236.     }
  237.     if ((new->use_canonical_name & 2) == 0) {
  238.     conf->use_canonical_name = new->use_canonical_name;
  239.     }
  240.  
  241. #ifdef RLIMIT_CPU
  242.     if (new->limit_cpu) {
  243.         conf->limit_cpu = new->limit_cpu;
  244.     }
  245. #endif
  246. #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
  247.     if (new->limit_mem) {
  248.         conf->limit_mem = new->limit_mem;
  249.     }
  250. #endif
  251. #ifdef RLIMIT_NPROC    
  252.     if (new->limit_nproc) {
  253.         conf->limit_nproc = new->limit_nproc;
  254.     }
  255. #endif
  256.  
  257.     if (new->limit_req_body) {
  258.         conf->limit_req_body = new->limit_req_body;
  259.     }
  260.     conf->sec = ap_append_arrays(a, base->sec, new->sec);
  261.  
  262.     if (new->satisfy != SATISFY_NOSPEC) {
  263.         conf->satisfy = new->satisfy;
  264.     }
  265.     return (void*)conf;
  266. }
  267.  
  268. static void *create_core_server_config(pool *a, server_rec *s)
  269. {
  270.     core_server_config *conf;
  271.     int is_virtual = s->is_virtual;
  272.   
  273.     conf = (core_server_config *)ap_pcalloc(a, sizeof(core_server_config));
  274. #ifdef GPROF
  275.     conf->gprof_dir = NULL;
  276. #endif
  277.     conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
  278.     conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
  279.     conf->sec = ap_make_array(a, 40, sizeof(void *));
  280.     conf->sec_url = ap_make_array(a, 40, sizeof(void *));
  281.     
  282.     return (void *)conf;
  283. }
  284.  
  285. static void *merge_core_server_configs(pool *p, void *basev, void *virtv)
  286. {
  287.     core_server_config *base = (core_server_config *)basev;
  288.     core_server_config *virt = (core_server_config *)virtv;
  289.     core_server_config *conf;
  290.  
  291.     conf = (core_server_config *)ap_pcalloc(p, sizeof(core_server_config));
  292.     *conf = *virt;
  293.     if (!conf->access_name) {
  294.         conf->access_name = base->access_name;
  295.     }
  296.     if (!conf->ap_document_root) {
  297.         conf->ap_document_root = base->ap_document_root;
  298.     }
  299.     conf->sec = ap_append_arrays(p, base->sec, virt->sec);
  300.     conf->sec_url = ap_append_arrays(p, base->sec_url, virt->sec_url);
  301.  
  302.     return conf;
  303. }
  304.  
  305. /* Add per-directory configuration entry (for <directory> section);
  306.  * these are part of the core server config.
  307.  */
  308.  
  309. CORE_EXPORT(void) ap_add_per_dir_conf(server_rec *s, void *dir_config)
  310. {
  311.     core_server_config *sconf = ap_get_module_config(s->module_config,
  312.                              &core_module);
  313.     void **new_space = (void **)ap_push_array(sconf->sec);
  314.     
  315.     *new_space = dir_config;
  316. }
  317.  
  318. CORE_EXPORT(void) ap_add_per_url_conf(server_rec *s, void *url_config)
  319. {
  320.     core_server_config *sconf = ap_get_module_config(s->module_config,
  321.                              &core_module);
  322.     void **new_space = (void **)ap_push_array(sconf->sec_url);
  323.     
  324.     *new_space = url_config;
  325. }
  326.  
  327. static void add_file_conf(core_dir_config *conf, void *url_config)
  328. {
  329.     void **new_space = (void **)ap_push_array(conf->sec);
  330.     
  331.     *new_space = url_config;
  332. }
  333.  
  334. /* core_reorder_directories reorders the directory sections such that the
  335.  * 1-component sections come first, then the 2-component, and so on, finally
  336.  * followed by the "special" sections.  A section is "special" if it's a regex,
  337.  * or if it doesn't start with / -- consider proxy: matching.  All movements
  338.  * are in-order to preserve the ordering of the sections from the config files.
  339.  * See directory_walk().
  340.  */
  341.  
  342. #if defined(OS2) || defined(WIN32)
  343. #define IS_SPECIAL(entry_core)    \
  344.     ((entry_core)->r != NULL \
  345.     || ((entry_core)->d[0] != '/' && (entry_core)->d[1] != ':'))
  346. #else
  347. #define IS_SPECIAL(entry_core)    \
  348.     ((entry_core)->r != NULL || (entry_core)->d[0] != '/')
  349. #endif
  350.  
  351. /* We need to do a stable sort, qsort isn't stable.  So to make it stable
  352.  * we'll be maintaining the original index into the list, and using it
  353.  * as the minor key during sorting.  The major key is the number of
  354.  * components (where a "special" section has infinite components).
  355.  */
  356. struct reorder_sort_rec {
  357.     void *elt;
  358.     int orig_index;
  359. };
  360.  
  361. static int reorder_sorter(const void *va, const void *vb)
  362. {
  363.     const struct reorder_sort_rec *a = va;
  364.     const struct reorder_sort_rec *b = vb;
  365.     core_dir_config *core_a;
  366.     core_dir_config *core_b;
  367.  
  368.     core_a = (core_dir_config *)ap_get_module_config(a->elt, &core_module);
  369.     core_b = (core_dir_config *)ap_get_module_config(b->elt, &core_module);
  370.     if (IS_SPECIAL(core_a)) {
  371.     if (!IS_SPECIAL(core_b)) {
  372.         return 1;
  373.     }
  374.     }
  375.     else if (IS_SPECIAL(core_b)) {
  376.     return -1;
  377.     }
  378.     else {
  379.     /* we know they're both not special */
  380.     if (core_a->d_components < core_b->d_components) {
  381.         return -1;
  382.     }
  383.     else if (core_a->d_components > core_b->d_components) {
  384.         return 1;
  385.     }
  386.     }
  387.     /* Either they're both special, or they're both not special and have the
  388.      * same number of components.  In any event, we now have to compare
  389.      * the minor key. */
  390.     return a->orig_index - b->orig_index;
  391. }
  392.  
  393. void ap_core_reorder_directories(pool *p, server_rec *s)
  394. {
  395.     core_server_config *sconf;
  396.     array_header *sec;
  397.     struct reorder_sort_rec *sortbin;
  398.     int nelts;
  399.     void **elts;
  400.     int i;
  401.  
  402.     /* XXX: we are about to waste some ram ... we will build a new array
  403.      * and we need some scratch space to do it.  The old array and the
  404.      * scratch space are never freed.
  405.      */
  406.     sconf = ap_get_module_config(s->module_config, &core_module);
  407.     sec = sconf->sec;
  408.     nelts = sec->nelts;
  409.     elts = (void **)sec->elts;
  410.  
  411.     /* build our sorting space */
  412.     sortbin = ap_palloc(p, sec->nelts * sizeof(*sortbin));
  413.     for (i = 0; i < nelts; ++i) {
  414.     sortbin[i].orig_index = i;
  415.     sortbin[i].elt = elts[i];
  416.     }
  417.  
  418.     qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter);
  419.  
  420.     /* and now build a new array */
  421.     /* XXX: uh I don't see why we can't reuse the old array, what
  422.      * was I thinking? -djg */
  423.     sec = ap_make_array(p, nelts, sizeof(void *));
  424.     for (i = 0; i < nelts; ++i) {
  425.     *(void **)ap_push_array(sec) = sortbin[i].elt;
  426.     }
  427.  
  428.     sconf->sec = sec;
  429. }
  430.  
  431. /*****************************************************************
  432.  *
  433.  * There are some elements of the core config structures in which
  434.  * other modules have a legitimate interest (this is ugly, but necessary
  435.  * to preserve NCSA back-compatibility).  So, we have a bunch of accessors
  436.  * here...
  437.  */
  438.  
  439. API_EXPORT(int) ap_allow_options(request_rec *r)
  440. {
  441.     core_dir_config *conf = 
  442.       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
  443.  
  444.     return conf->opts; 
  445.  
  446. API_EXPORT(int) ap_allow_overrides(request_rec *r) 
  447.     core_dir_config *conf;
  448.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  449.                            &core_module); 
  450.  
  451.     return conf->override; 
  452.  
  453. API_EXPORT(const char *) ap_auth_type(request_rec *r)
  454. {
  455.     core_dir_config *conf;
  456.  
  457.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  458.                            &core_module); 
  459.     return conf->ap_auth_type;
  460. }
  461.  
  462. API_EXPORT(const char *) ap_auth_name(request_rec *r)
  463. {
  464.     core_dir_config *conf;
  465.  
  466.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  467.                            &core_module); 
  468.     return conf->ap_auth_name;
  469. }
  470.  
  471. API_EXPORT(const char *) ap_default_type(request_rec *r)
  472. {
  473.     core_dir_config *conf;
  474.  
  475.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  476.                            &core_module); 
  477.     return conf->ap_default_type 
  478.                ? conf->ap_default_type 
  479.                : DEFAULT_CONTENT_TYPE;
  480. }
  481.  
  482. API_EXPORT(const char *) ap_document_root(request_rec *r) /* Don't use this! */
  483. {
  484.     core_server_config *conf;
  485.  
  486.     conf = (core_server_config *)ap_get_module_config(r->server->module_config,
  487.                               &core_module); 
  488.     return conf->ap_document_root;
  489. }
  490.  
  491. API_EXPORT(const array_header *) ap_requires(request_rec *r)
  492. {
  493.     core_dir_config *conf;
  494.  
  495.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  496.                            &core_module); 
  497.     return conf->ap_requires;
  498. }
  499.  
  500. API_EXPORT(int) ap_satisfies(request_rec *r)
  501. {
  502.     core_dir_config *conf;
  503.  
  504.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  505.                            &core_module);
  506.  
  507.     return conf->satisfy;
  508. }
  509.  
  510. /* Should probably just get rid of this... the only code that cares is
  511.  * part of the core anyway (and in fact, it isn't publicised to other
  512.  * modules).
  513.  */
  514.  
  515. char *ap_response_code_string(request_rec *r, int error_index)
  516. {
  517.     core_dir_config *conf;
  518.  
  519.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  520.                            &core_module); 
  521.  
  522.     if (conf->response_code_strings == NULL) {
  523.     return NULL;
  524.     }
  525.     return conf->response_code_strings[error_index];
  526. }
  527.  
  528.  
  529. /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
  530. static ap_inline void do_double_reverse (conn_rec *conn)
  531. {
  532.     struct hostent *hptr;
  533.  
  534.     if (conn->double_reverse) {
  535.     /* already done */
  536.     return;
  537.     }
  538.     if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
  539.     /* single reverse failed, so don't bother */
  540.     conn->double_reverse = -1;
  541.     return;
  542.     }
  543.     hptr = gethostbyname(conn->remote_host);
  544.     if (hptr) {
  545.     char **haddr;
  546.  
  547.     for (haddr = hptr->h_addr_list; *haddr; haddr++) {
  548.         if (((struct in_addr *)(*haddr))->s_addr
  549.         == conn->remote_addr.sin_addr.s_addr) {
  550.         conn->double_reverse = 1;
  551.         return;
  552.         }
  553.     }
  554.     }
  555.     conn->double_reverse = -1;
  556. }
  557.  
  558. API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
  559.                         int type)
  560. {
  561.     struct in_addr *iaddr;
  562.     struct hostent *hptr;
  563.     int hostname_lookups;
  564.     int old_stat = SERVER_DEAD;    /* we shouldn't ever be in this state */
  565.  
  566.     /* If we haven't checked the host name, and we want to */
  567.     if (dir_config) {
  568.     hostname_lookups =
  569.         ((core_dir_config *)ap_get_module_config(dir_config, &core_module))
  570.         ->hostname_lookups;
  571.     if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
  572.         hostname_lookups = HOSTNAME_LOOKUP_OFF;
  573.     }
  574.     }
  575.     else {
  576.     /* the default */
  577.     hostname_lookups = HOSTNAME_LOOKUP_OFF;
  578.     }
  579.  
  580.     if (type != REMOTE_NOLOOKUP
  581.     && conn->remote_host == NULL
  582.     && (type == REMOTE_DOUBLE_REV
  583.         || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
  584.     old_stat = ap_update_child_status(conn->child_num, SERVER_BUSY_DNS,
  585.                       (request_rec*)NULL);
  586.     iaddr = &(conn->remote_addr.sin_addr);
  587.     hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
  588.     if (hptr != NULL) {
  589.         conn->remote_host = ap_pstrdup(conn->pool, (void *)hptr->h_name);
  590.         ap_str_tolower(conn->remote_host);
  591.        
  592.         if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
  593.         do_double_reverse(conn);
  594.         if (conn->double_reverse != 1) {
  595.             conn->remote_host = NULL;
  596.         }
  597.         }
  598.     }
  599.     /* if failed, set it to the NULL string to indicate error */
  600.     if (conn->remote_host == NULL) {
  601.         conn->remote_host = "";
  602.     }
  603.     }
  604.     if (type == REMOTE_DOUBLE_REV) {
  605.     do_double_reverse(conn);
  606.     if (conn->double_reverse == -1) {
  607.         return NULL;
  608.     }
  609.     }
  610.     if (old_stat != SERVER_DEAD) {
  611.     (void)ap_update_child_status(conn->child_num, old_stat,
  612.                      (request_rec*)NULL);
  613.     }
  614.  
  615. /*
  616.  * Return the desired information; either the remote DNS name, if found,
  617.  * or either NULL (if the hostname was requested) or the IP address
  618.  * (if any identifier was requested).
  619.  */
  620.     if (conn->remote_host != NULL && conn->remote_host[0] != '\0') {
  621.     return conn->remote_host;
  622.     }
  623.     else {
  624.     if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) {
  625.         return NULL;
  626.     }
  627.     else {
  628.         return conn->remote_ip;
  629.     }
  630.     }
  631. }
  632.  
  633. API_EXPORT(const char *) ap_get_remote_logname(request_rec *r)
  634. {
  635.     core_dir_config *dir_conf;
  636.  
  637.     if (r->connection->remote_logname != NULL) {
  638.     return r->connection->remote_logname;
  639.     }
  640.  
  641. /* If we haven't checked the identity, and we want to */
  642.     dir_conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  643.                                &core_module);
  644.  
  645.     if (dir_conf->do_rfc1413 & 1) {
  646.     return ap_rfc1413(r->connection, r->server);
  647.     }
  648.     else {
  649.     return NULL;
  650.     }
  651. }
  652.  
  653. /* There are two options regarding what the "name" of a server is.  The
  654.  * "canonical" name as defined by ServerName and Port, or the "client's
  655.  * name" as supplied by a possible Host: header or full URI.  We never
  656.  * trust the port passed in the client's headers, we always use the
  657.  * port of the actual socket.
  658.  */
  659. API_EXPORT(const char *) ap_get_server_name(const request_rec *r)
  660. {
  661.     core_dir_config *d;
  662.  
  663.     d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  664.                         &core_module);
  665.     if (d->use_canonical_name & 1) {
  666.     return r->server->server_hostname;
  667.     }
  668.     return r->hostname ? r->hostname : r->server->server_hostname;
  669. }
  670.  
  671. API_EXPORT(unsigned) ap_get_server_port(const request_rec *r)
  672. {
  673.     unsigned port;
  674.     core_dir_config *d =
  675.       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
  676.     
  677.     port = r->server->port ? r->server->port : ap_default_port(r);
  678.  
  679.     if (d->use_canonical_name & 1) {
  680.     return port;
  681.     }
  682.     return r->hostname ? ntohs(r->connection->local_addr.sin_port)
  683.                : port;
  684. }
  685.  
  686. API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
  687.                     const request_rec *r)
  688. {
  689.     unsigned port;
  690.     const char *host;
  691.     core_dir_config *d =
  692.       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
  693.  
  694.     if (d->use_canonical_name & 1) {
  695.     port = r->server->port ? r->server->port : ap_default_port(r);
  696.     host = r->server->server_hostname;
  697.     }
  698.     else {
  699.         if (r->hostname) {
  700.             port = ntohs(r->connection->local_addr.sin_port);
  701.     }
  702.         else if (r->server->port) {
  703.             port = r->server->port;
  704.     }
  705.         else {
  706.             port = ap_default_port(r);
  707.     }
  708.  
  709.     host = r->hostname ? r->hostname : r->server->server_hostname;
  710.     }
  711.     if (ap_is_default_port(port, r)) {
  712.     return ap_pstrcat(p, ap_http_method(r), "://", host, uri, NULL);
  713.     }
  714.     return ap_psprintf(p, "%s://%s:%u%s", ap_http_method(r), host, port, uri);
  715. }
  716.  
  717. API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r)
  718. {
  719.     core_dir_config *d =
  720.       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
  721.     
  722.     return d->limit_req_body;
  723. }
  724.  
  725. /*****************************************************************
  726.  *
  727.  * Commands... this module handles almost all of the NCSA httpd.conf
  728.  * commands, but most of the old srm.conf is in the the modules.
  729.  */
  730.  
  731. static const char end_directory_section[] = "</Directory>";
  732. static const char end_directorymatch_section[] = "</DirectoryMatch>";
  733. static const char end_location_section[] = "</Location>";
  734. static const char end_locationmatch_section[] = "</LocationMatch>";
  735. static const char end_files_section[] = "</Files>";
  736. static const char end_filesmatch_section[] = "</FilesMatch>";
  737. static const char end_virtualhost_section[] = "</VirtualHost>";
  738. static const char end_ifmodule_section[] = "</IfModule>";
  739. static const char end_ifdefine_section[] = "</IfDefine>";
  740.  
  741.  
  742. API_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd,
  743.                           unsigned forbidden)
  744. {
  745.     const char *gt = (cmd->cmd->name[0] == '<'
  746.               && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>')
  747.                          ? ">" : "";
  748.  
  749.     if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual) {
  750.     return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
  751.               " cannot occur within <VirtualHost> section", NULL);
  752.     }
  753.  
  754.     if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) {
  755.     return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
  756.               " cannot occur within <Limit> section", NULL);
  757.     }
  758.  
  759.     if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE
  760.     && cmd->path != NULL) {
  761.     return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
  762.               " cannot occur within <Directory/Location/Files> "
  763.               "section", NULL);
  764.     }
  765.     
  766.     if (((forbidden & NOT_IN_DIRECTORY)
  767.      && (cmd->end_token == end_directory_section
  768.          || cmd->end_token == end_directorymatch_section)) 
  769.     || ((forbidden & NOT_IN_LOCATION)
  770.         && (cmd->end_token == end_location_section
  771.         || cmd->end_token == end_locationmatch_section)) 
  772.     || ((forbidden & NOT_IN_FILES)
  773.         && (cmd->end_token == end_files_section
  774.         || cmd->end_token == end_filesmatch_section))) {
  775.     return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
  776.               " cannot occur within <", cmd->end_token+2,
  777.               " section", NULL);
  778.     }
  779.  
  780.     return NULL;
  781. }
  782.  
  783. static const char *set_access_name(cmd_parms *cmd, void *dummy, char *arg)
  784. {
  785.     void *sconf = cmd->server->module_config;
  786.     core_server_config *conf = ap_get_module_config(sconf, &core_module);
  787.  
  788.     const char *err = ap_check_cmd_context(cmd,
  789.                        NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  790.     if (err != NULL) {
  791.         return err;
  792.     }
  793.  
  794.     conf->access_name = ap_pstrdup(cmd->pool, arg);
  795.     return NULL;
  796. }
  797.  
  798. #ifdef GPROF
  799. static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, char *arg)
  800. {
  801.     void *sconf = cmd->server->module_config;
  802.     core_server_config *conf = ap_get_module_config(sconf, &core_module);
  803.  
  804.     const char *err = ap_check_cmd_context(cmd,
  805.                        NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  806.     if (err != NULL) {
  807.         return err;
  808.     }
  809.  
  810.     conf->gprof_dir = ap_pstrdup(cmd->pool, arg);
  811.     return NULL;
  812. }
  813. #endif /*GPROF*/
  814.  
  815. static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg)
  816. {
  817.     void *sconf = cmd->server->module_config;
  818.     core_server_config *conf = ap_get_module_config(sconf, &core_module);
  819.   
  820.     const char *err = ap_check_cmd_context(cmd,
  821.                        NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  822.     if (err != NULL) {
  823.         return err;
  824.     }
  825.  
  826.     arg = ap_os_canonical_filename(cmd->pool, arg);
  827.     if (!ap_is_directory(arg)) {
  828.     if (cmd->server->is_virtual) {
  829.         fprintf(stderr, "Warning: DocumentRoot [%s] does not exist\n",
  830.             arg);
  831.     }
  832.     else {
  833.         return "DocumentRoot must be a directory";
  834.     }
  835.     }
  836.     
  837.     conf->ap_document_root = arg;
  838.     return NULL;
  839. }
  840.  
  841. API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string)
  842. {
  843.     core_dir_config *conf = 
  844.     ap_get_module_config(r->per_dir_config, &core_module);
  845.     int idx;
  846.  
  847.     if(conf->response_code_strings == NULL) {
  848.         conf->response_code_strings = 
  849.         ap_pcalloc(r->pool,
  850.             sizeof(*conf->response_code_strings) * 
  851.             RESPONSE_CODES);
  852.     }
  853.  
  854.     idx = ap_index_of_response(status);
  855.  
  856.     conf->response_code_strings[idx] = 
  857.        ((ap_is_url(string) || (*string == '/')) && (*string != '"')) ? 
  858.        ap_pstrdup(r->pool, string) : ap_pstrcat(r->pool, "\"", string, NULL);
  859. }
  860.  
  861. static const char *set_error_document(cmd_parms *cmd, core_dir_config *conf,
  862.                       char *line)
  863. {
  864.     int error_number, index_number, idx500;
  865.     char *w;
  866.                 
  867.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  868.     if (err != NULL) {
  869.         return err;
  870.     }
  871.  
  872.     /* 1st parameter should be a 3 digit number, which we recognize;
  873.      * convert it into an array index
  874.      */
  875.   
  876.     w = ap_getword_conf_nc(cmd->pool, &line);
  877.     error_number = atoi(w);
  878.  
  879.     idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
  880.  
  881.     if (error_number == HTTP_INTERNAL_SERVER_ERROR) {
  882.         index_number = idx500;
  883.     }
  884.     else if ((index_number = ap_index_of_response(error_number)) == idx500) {
  885.         return ap_pstrcat(cmd->pool, "Unsupported HTTP response code ",
  886.               w, NULL);
  887.     }
  888.  
  889.     /* The entry should be ignored if it is a full URL for a 401 error */
  890.  
  891.     if (error_number == 401 &&
  892.     line[0] != '/' && line[0] != '"') { /* Ignore it... */
  893.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, NULL,
  894.              "cannot use a full URL in a 401 ErrorDocument "
  895.              "directive --- ignoring!");
  896.     }
  897.     else { /* Store it... */
  898.         if (conf->response_code_strings == NULL) {
  899.         conf->response_code_strings =
  900.         ap_pcalloc(cmd->pool,
  901.                sizeof(*conf->response_code_strings) * RESPONSE_CODES);
  902.         }
  903.         conf->response_code_strings[index_number] = ap_pstrdup(cmd->pool, line);
  904.     }   
  905.  
  906.     return NULL;
  907. }
  908.  
  909. /* access.conf commands...
  910.  *
  911.  * The *only* thing that can appear in access.conf at top level is a
  912.  * <Directory> section.  NB we need to have a way to cut the srm_command_loop
  913.  * invoked by dirsection (i.e., <Directory>) short when </Directory> is seen.
  914.  * We do that by returning an error, which dirsection itself recognizes and
  915.  * discards as harmless.  Cheesy, but it works.
  916.  */
  917.  
  918. static const char *set_override(cmd_parms *cmd, core_dir_config *d,
  919.                 const char *l)
  920. {
  921.     char *w;
  922.   
  923.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  924.     if (err != NULL) {
  925.         return err;
  926.     }
  927.  
  928.     d->override = OR_NONE;
  929.     while (l[0]) {
  930.         w = ap_getword_conf(cmd->pool, &l);
  931.     if (!strcasecmp(w, "Limit")) {
  932.         d->override |= OR_LIMIT;
  933.     }
  934.     else if (!strcasecmp(w, "Options")) {
  935.         d->override |= OR_OPTIONS;
  936.     }
  937.     else if (!strcasecmp(w, "FileInfo")) {
  938.             d->override |= OR_FILEINFO;
  939.     }
  940.     else if (!strcasecmp(w, "AuthConfig")) {
  941.         d->override |= OR_AUTHCFG;
  942.     }
  943.     else if (!strcasecmp(w, "Indexes")) {
  944.             d->override |= OR_INDEXES;
  945.     }
  946.     else if (!strcasecmp(w, "None")) {
  947.         d->override = OR_NONE;
  948.     }
  949.     else if (!strcasecmp(w, "All")) {
  950.         d->override = OR_ALL;
  951.     }
  952.     else {
  953.         return ap_pstrcat(cmd->pool, "Illegal override option ", w, NULL);
  954.     }
  955.     d->override &= ~OR_UNSET;
  956.     }
  957.  
  958.     return NULL;
  959. }
  960.  
  961. static const char *set_options(cmd_parms *cmd, core_dir_config *d,
  962.                    const char *l)
  963. {
  964.     allow_options_t opt;
  965.     int first = 1;
  966.     char action;
  967.  
  968.     while (l[0]) {
  969.         char *w = ap_getword_conf(cmd->pool, &l);
  970.     action = '\0';
  971.  
  972.     if (*w == '+' || *w == '-') {
  973.         action = *(w++);
  974.     }
  975.     else if (first) {
  976.           d->opts = OPT_NONE;
  977.             first = 0;
  978.         }
  979.         
  980.     if (!strcasecmp(w, "Indexes")) {
  981.         opt = OPT_INDEXES;
  982.     }
  983.     else if (!strcasecmp(w, "Includes")) {
  984.         opt = OPT_INCLUDES;
  985.     }
  986.     else if (!strcasecmp(w, "IncludesNOEXEC")) {
  987.         opt = (OPT_INCLUDES | OPT_INCNOEXEC);
  988.     }
  989.     else if (!strcasecmp(w, "FollowSymLinks")) {
  990.         opt = OPT_SYM_LINKS;
  991.     }
  992.     else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
  993.         opt = OPT_SYM_OWNER;
  994.     }
  995.     else if (!strcasecmp(w, "execCGI")) {
  996.         opt = OPT_EXECCGI;
  997.     }
  998.     else if (!strcasecmp(w, "MultiViews")) {
  999.         opt = OPT_MULTI;
  1000.     }
  1001.     else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
  1002.         opt = OPT_MULTI|OPT_EXECCGI;
  1003.     }
  1004.     else if (!strcasecmp(w, "None")) {
  1005.         opt = OPT_NONE;
  1006.     }
  1007.     else if (!strcasecmp(w, "All")) {
  1008.         opt = OPT_ALL;
  1009.     }
  1010.     else {
  1011.         return ap_pstrcat(cmd->pool, "Illegal option ", w, NULL);
  1012.     }
  1013.  
  1014.     /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
  1015.     if (action == '-') {
  1016.         d->opts_remove |= opt;
  1017.         d->opts_add &= ~opt;
  1018.         d->opts &= ~opt;
  1019.     }
  1020.     else if (action == '+') {
  1021.         d->opts_add |= opt;
  1022.         d->opts_remove &= ~opt;
  1023.         d->opts |= opt;
  1024.     }
  1025.     else {
  1026.         d->opts |= opt;
  1027.     }
  1028.     }
  1029.  
  1030.     return NULL;
  1031. }
  1032.  
  1033. static const char *satisfy(cmd_parms *cmd, core_dir_config *c, char *arg)
  1034. {
  1035.     if (!strcasecmp(arg, "all")) {
  1036.         c->satisfy = SATISFY_ALL;
  1037.     }
  1038.     else if (!strcasecmp(arg, "any")) {
  1039.         c->satisfy = SATISFY_ANY;
  1040.     }
  1041.     else {
  1042.         return "Satisfy either 'any' or 'all'.";
  1043.     }
  1044.     return NULL;
  1045. }
  1046.  
  1047. static const char *require(cmd_parms *cmd, core_dir_config *c, char *arg)
  1048. {
  1049.     require_line *r;
  1050.   
  1051.     if (!c->ap_requires) {
  1052.         c->ap_requires = ap_make_array(cmd->pool, 2, sizeof(require_line));
  1053.     }
  1054.     r = (require_line *)ap_push_array(c->ap_requires);
  1055.     r->requirement = ap_pstrdup(cmd->pool, arg);
  1056.     r->method_mask = cmd->limited;
  1057.     return NULL;
  1058. }
  1059.  
  1060. CORE_EXPORT_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy,
  1061.                           const char *arg)
  1062. {
  1063.     const char *limited_methods = ap_getword(cmd->pool, &arg, '>');
  1064.     int limited = 0;
  1065.   
  1066.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  1067.     if (err != NULL) {
  1068.         return err;
  1069.     }
  1070.  
  1071.     /* XXX: NB: Currently, we have no way of checking
  1072.      * whether <Limit> sections are closed properly.
  1073.      * (If we would add a srm_command_loop() here we might...)
  1074.      */
  1075.     
  1076.     while (limited_methods[0]) {
  1077.         char *method = ap_getword_conf(cmd->pool, &limited_methods);
  1078.         int  methnum = ap_method_number_of(method);
  1079.  
  1080.         if (methnum == M_TRACE) {
  1081.             return "TRACE cannot be controlled by <Limit>";
  1082.         }
  1083.         else if (methnum == M_INVALID) {
  1084.             return ap_pstrcat(cmd->pool, "unknown method \"",
  1085.                               method, "\" in <Limit>", NULL);
  1086.         }
  1087.         else {
  1088.             limited |= (1 << methnum);
  1089.         }
  1090.     }
  1091.  
  1092.     cmd->limited = limited;
  1093.     return NULL;
  1094. }
  1095.  
  1096. static const char *endlimit_section(cmd_parms *cmd, void *dummy, void *dummy2)
  1097. {
  1098.     if (cmd->limited == -1) {
  1099.         return "</Limit> unexpected";
  1100.     }
  1101.     
  1102.     cmd->limited = -1;
  1103.     return NULL;
  1104. }
  1105.  
  1106. /*
  1107.  * When a section is not closed properly when end-of-file is reached,
  1108.  * then an error message should be printed:
  1109.  */
  1110. static const char *missing_endsection(cmd_parms *cmd, int nest)
  1111. {
  1112.     if (nest < 2) {
  1113.     return ap_psprintf(cmd->pool, "Missing %s directive at end-of-file",
  1114.                cmd->end_token);
  1115.     }
  1116.     return ap_psprintf(cmd->pool, "%d missing %s directives at end-of-file",
  1117.                nest, cmd->end_token);
  1118. }
  1119.  
  1120. /* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that 
  1121.  * people don't get bitten by wrong-cased regex matches
  1122.  */
  1123.  
  1124. #ifdef WIN32
  1125. #define USE_ICASE REG_ICASE
  1126. #else
  1127. #define USE_ICASE 0
  1128. #endif
  1129.  
  1130. static const char *end_nested_section(cmd_parms *cmd, void *dummy)
  1131. {
  1132.     if (cmd->end_token == NULL) {
  1133.         return ap_pstrcat(cmd->pool, cmd->cmd->name,
  1134.               " without matching <", cmd->cmd->name + 2, 
  1135.               " section", NULL);
  1136.     }
  1137.     /*
  1138.      * This '!=' may look weird on a string comparison, but it's correct --
  1139.      * it's been set up so that checking for two pointers to the same datum
  1140.      * is valid here.  And faster.
  1141.      */
  1142.     if (cmd->cmd->name != cmd->end_token) {
  1143.     return ap_pstrcat(cmd->pool, "Expected ", cmd->end_token, " but saw ",
  1144.               cmd->cmd->name, NULL);
  1145.     }
  1146.     return cmd->end_token;
  1147. }
  1148.  
  1149. /*
  1150.  * Report a missing-'>' syntax error.
  1151.  */
  1152. static char *unclosed_directive(cmd_parms *cmd)
  1153. {
  1154.     return ap_pstrcat(cmd->pool, cmd->cmd->name,
  1155.               "> directive missing closing '>'", NULL);
  1156. }
  1157.  
  1158. static const char *dirsection(cmd_parms *cmd, void *dummy, const char *arg)
  1159. {
  1160.     const char *errmsg;
  1161.     char *endp = strrchr(arg, '>');
  1162.     int old_overrides = cmd->override;
  1163.     char *old_path = cmd->path;
  1164.     core_dir_config *conf;
  1165.     void *new_dir_conf = ap_create_per_dir_config(cmd->pool);
  1166.     regex_t *r = NULL;
  1167.     const char *old_end_token;
  1168.     const command_rec *thiscmd = cmd->cmd;
  1169.  
  1170.     const char *err = ap_check_cmd_context(cmd,
  1171.                        NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1172.     if (err != NULL) {
  1173.         return err;
  1174.     }
  1175.  
  1176.     if (endp == NULL) {
  1177.     return unclosed_directive(cmd);
  1178.     }
  1179.  
  1180.     *endp = '\0';
  1181.  
  1182.     cmd->path = ap_getword_conf(cmd->pool, &arg);
  1183. #ifdef OS2
  1184.     /* Fix OS/2 HPFS filename case problem. */
  1185.     cmd->path = strlwr(cmd->path);
  1186. #endif    
  1187.     cmd->override = OR_ALL|ACCESS_CONF;
  1188.  
  1189.     if (thiscmd->cmd_data) { /* <DirectoryMatch> */
  1190.     r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
  1191.     }
  1192.     else if (!strcmp(cmd->path, "~")) {
  1193.     cmd->path = ap_getword_conf(cmd->pool, &arg);
  1194.     r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
  1195.     }
  1196.     else {
  1197.     /* Ensure that the pathname is canonical */
  1198.     cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
  1199.     }
  1200.  
  1201.     old_end_token = cmd->end_token;
  1202.     cmd->end_token = thiscmd->cmd_data ? end_directorymatch_section : end_directory_section;
  1203.     errmsg = ap_srm_command_loop(cmd, new_dir_conf);
  1204.     if (errmsg == NULL) {
  1205.     errmsg = missing_endsection(cmd, 1);
  1206.     }
  1207.     cmd->end_token = old_end_token;
  1208.     if (errmsg != (thiscmd->cmd_data 
  1209.                ? end_directorymatch_section 
  1210.            : end_directory_section)) {
  1211.     return errmsg;
  1212.     }
  1213.  
  1214.     conf = (core_dir_config *)ap_get_module_config(new_dir_conf, &core_module);
  1215.     conf->r = r;
  1216.  
  1217.     ap_add_per_dir_conf(cmd->server, new_dir_conf);
  1218.  
  1219.     if (*arg != '\0') {
  1220.     return ap_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
  1221.               "> arguments not (yet) supported.", NULL);
  1222.     }
  1223.  
  1224.     cmd->path = old_path;
  1225.     cmd->override = old_overrides;
  1226.  
  1227.     return NULL;
  1228. }
  1229.  
  1230. static const char *urlsection(cmd_parms *cmd, void *dummy, const char *arg)
  1231. {
  1232.     const char *errmsg;
  1233.     char *endp = strrchr(arg, '>');
  1234.     int old_overrides = cmd->override;
  1235.     char *old_path = cmd->path;
  1236.     core_dir_config *conf;
  1237.     regex_t *r = NULL;
  1238.     const char *old_end_token;
  1239.     const command_rec *thiscmd = cmd->cmd;
  1240.  
  1241.     void *new_url_conf = ap_create_per_dir_config(cmd->pool);
  1242.  
  1243.     const char *err = ap_check_cmd_context(cmd,
  1244.                        NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1245.     if (err != NULL) {
  1246.         return err;
  1247.     }
  1248.  
  1249.     if (endp == NULL) {
  1250.     return unclosed_directive(cmd);
  1251.     }
  1252.  
  1253.     *endp = '\0';
  1254.  
  1255.     cmd->path = ap_getword_conf(cmd->pool, &arg);
  1256.     cmd->override = OR_ALL|ACCESS_CONF;
  1257.  
  1258.     if (thiscmd->cmd_data) { /* <LocationMatch> */
  1259.     r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
  1260.     }
  1261.     else if (!strcmp(cmd->path, "~")) {
  1262.     cmd->path = ap_getword_conf(cmd->pool, &arg);
  1263.     r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
  1264.     }
  1265.  
  1266.     old_end_token = cmd->end_token;
  1267.     cmd->end_token = thiscmd->cmd_data ? end_locationmatch_section
  1268.                                        : end_location_section;
  1269.     errmsg = ap_srm_command_loop(cmd, new_url_conf);
  1270.     if (errmsg == NULL) {
  1271.     errmsg = missing_endsection(cmd, 1);
  1272.     }
  1273.     cmd->end_token = old_end_token;
  1274.     if (errmsg != (thiscmd->cmd_data 
  1275.                ? end_locationmatch_section 
  1276.                : end_location_section)) {
  1277.     return errmsg;
  1278.     }
  1279.  
  1280.     conf = (core_dir_config *)ap_get_module_config(new_url_conf, &core_module);
  1281.     conf->d = ap_pstrdup(cmd->pool, cmd->path);    /* No mangling, please */
  1282.     conf->d_is_fnmatch = ap_is_fnmatch(conf->d) != 0;
  1283.     conf->r = r;
  1284.  
  1285.     ap_add_per_url_conf(cmd->server, new_url_conf);
  1286.     
  1287.     if (*arg != '\0') {
  1288.     return ap_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
  1289.               "> arguments not (yet) supported.", NULL);
  1290.     }
  1291.  
  1292.     cmd->path = old_path;
  1293.     cmd->override = old_overrides;
  1294.  
  1295.     return NULL;
  1296. }
  1297.  
  1298. static const char *filesection(cmd_parms *cmd, core_dir_config *c,
  1299.                    const char *arg)
  1300. {
  1301.     const char *errmsg;
  1302.     char *endp = strrchr(arg, '>');
  1303.     int old_overrides = cmd->override;
  1304.     char *old_path = cmd->path;
  1305.     core_dir_config *conf;
  1306.     regex_t *r = NULL;
  1307.     const char *old_end_token;
  1308.     const command_rec *thiscmd = cmd->cmd;
  1309.  
  1310.     void *new_file_conf = ap_create_per_dir_config(cmd->pool);
  1311.  
  1312.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_LOCATION);
  1313.     if (err != NULL) {
  1314.         return err;
  1315.     }
  1316.  
  1317.     if (endp == NULL) {
  1318.     return unclosed_directive(cmd);
  1319.     }
  1320.  
  1321.     *endp = '\0';
  1322.  
  1323.     cmd->path = ap_getword_conf(cmd->pool, &arg);
  1324.     /* Only if not an .htaccess file */
  1325.     if (!old_path) {
  1326.     cmd->override = OR_ALL|ACCESS_CONF;
  1327.     }
  1328.  
  1329.     if (thiscmd->cmd_data) { /* <FilesMatch> */
  1330.         r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
  1331.     }
  1332.     else if (!strcmp(cmd->path, "~")) {
  1333.     cmd->path = ap_getword_conf(cmd->pool, &arg);
  1334.     r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
  1335.     }
  1336.     else {
  1337.     /* Ensure that the pathname is canonical */
  1338.     cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
  1339.     }
  1340.  
  1341.     old_end_token = cmd->end_token;
  1342.     cmd->end_token = thiscmd->cmd_data ? end_filesmatch_section : end_files_section;
  1343.     errmsg = ap_srm_command_loop(cmd, new_file_conf);
  1344.     if (errmsg == NULL) {
  1345.     errmsg = missing_endsection(cmd, 1);
  1346.     }
  1347.     cmd->end_token = old_end_token;
  1348.     if (errmsg != (thiscmd->cmd_data 
  1349.                ? end_filesmatch_section 
  1350.            : end_files_section)) {
  1351.     return errmsg;
  1352.     }
  1353.  
  1354.     conf = (core_dir_config *)ap_get_module_config(new_file_conf,
  1355.                            &core_module);
  1356.     conf->d = cmd->path;
  1357.     conf->d_is_fnmatch = ap_is_fnmatch(conf->d) != 0;
  1358.     conf->r = r;
  1359.  
  1360.     add_file_conf(c, new_file_conf);
  1361.  
  1362.     if (*arg != '\0') {
  1363.     return ap_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
  1364.               "> arguments not (yet) supported.", NULL);
  1365.     }
  1366.  
  1367.     cmd->path = old_path;
  1368.     cmd->override = old_overrides;
  1369.  
  1370.     return NULL;
  1371. }
  1372.  
  1373. /* XXX: NB: Currently, we have no way of checking
  1374.  * whether <IfModule> sections are closed properly.
  1375.  * Extra (redundant, unpaired) </IfModule> directives are
  1376.  * simply silently ignored.
  1377.  */
  1378. static const char *end_ifmod(cmd_parms *cmd, void *dummy)
  1379. {
  1380.     return NULL;
  1381. }
  1382.  
  1383. static const char *start_ifmod(cmd_parms *cmd, void *dummy, char *arg)
  1384. {
  1385.     char *endp = strrchr(arg, '>');
  1386.     char l[MAX_STRING_LEN];
  1387.     int not = (arg[0] == '!');
  1388.     module *found;
  1389.     int nest = 1;
  1390.  
  1391.     if (endp == NULL) {
  1392.     return unclosed_directive(cmd);
  1393.     }
  1394.  
  1395.     *endp = '\0';
  1396.  
  1397.     if (not) {
  1398.         arg++;
  1399.     }
  1400.  
  1401.     found = ap_find_linked_module(arg);
  1402.  
  1403.     if ((!not && found) || (not && !found)) {
  1404.         return NULL;
  1405.     }
  1406.  
  1407.     while (nest && !(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
  1408.         if (!strncasecmp(l, "<IfModule", 9)) {
  1409.         nest++;
  1410.     }
  1411.     if (!strcasecmp(l, "</IfModule>")) {
  1412.       nest--;
  1413.     }
  1414.     }
  1415.  
  1416.     if (nest) {
  1417.     cmd->end_token = end_ifmodule_section;
  1418.     return missing_endsection(cmd, nest);
  1419.     }
  1420.     return NULL;
  1421. }
  1422.  
  1423. API_EXPORT(int) ap_exists_config_define(char *name)
  1424. {
  1425.     char **defines;
  1426.     int i;
  1427.  
  1428.     defines = (char **)ap_server_config_defines->elts;
  1429.     for (i = 0; i < ap_server_config_defines->nelts; i++) {
  1430.         if (strcmp(defines[i], name) == 0) {
  1431.             return 1;
  1432.     }
  1433.     }
  1434.     return 0;
  1435. }
  1436.  
  1437. static const char *end_ifdefine(cmd_parms *cmd, void *dummy) 
  1438. {
  1439.     return NULL;
  1440. }
  1441.  
  1442. static const char *start_ifdefine(cmd_parms *cmd, void *dummy, char *arg)
  1443. {
  1444.     char *endp;
  1445.     char l[MAX_STRING_LEN];
  1446.     int defined;
  1447.     int not = 0;
  1448.     int nest = 1;
  1449.  
  1450.     endp = strrchr(arg, '>');
  1451.     if (endp == NULL) {
  1452.     return unclosed_directive(cmd);
  1453.     }
  1454.  
  1455.     *endp = '\0';
  1456.  
  1457.     if (arg[0] == '!') {
  1458.         not = 1;
  1459.     arg++;
  1460.     }
  1461.  
  1462.     defined = ap_exists_config_define(arg);
  1463.  
  1464.     if ((!not && defined) || (not && !defined)) {
  1465.     return NULL;
  1466.     }
  1467.  
  1468.     while (nest && !(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
  1469.         if (!strncasecmp(l, "<IfDefine", 9)) {
  1470.         nest++;
  1471.     }
  1472.     if (!strcasecmp(l, "</IfDefine>")) {
  1473.         nest--;
  1474.     }
  1475.     }
  1476.     if (nest) {
  1477.     cmd->end_token = end_ifdefine_section;
  1478.     return missing_endsection(cmd, nest);
  1479.     }
  1480.     return NULL;
  1481. }
  1482.  
  1483. /* httpd.conf commands... beginning with the <VirtualHost> business */
  1484.  
  1485. static const char *virtualhost_section(cmd_parms *cmd, void *dummy, char *arg)
  1486. {
  1487.     server_rec *main_server = cmd->server, *s;
  1488.     const char *errmsg;
  1489.     char *endp = strrchr(arg, '>');
  1490.     pool *p = cmd->pool, *ptemp = cmd->temp_pool;
  1491.     const char *old_end_token;
  1492.  
  1493.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1494.     if (err != NULL) {
  1495.         return err;
  1496.     }
  1497.  
  1498.     if (endp == NULL) {
  1499.     return unclosed_directive(cmd);
  1500.     }
  1501.  
  1502.     *endp = '\0';
  1503.     
  1504.     /* FIXME: There's another feature waiting to happen here -- since you
  1505.     can now put multiple addresses/names on a single <VirtualHost>
  1506.     you might want to use it to group common definitions and then
  1507.     define other "subhosts" with their individual differences.  But
  1508.     personally I'd rather just do it with a macro preprocessor. -djg */
  1509.     if (main_server->is_virtual) {
  1510.     return "<VirtualHost> doesn't nest!";
  1511.     }
  1512.     
  1513.     errmsg = ap_init_virtual_host(p, arg, main_server, &s);
  1514.     if (errmsg) {
  1515.     return errmsg;
  1516.     }
  1517.  
  1518.     s->next = main_server->next;
  1519.     main_server->next = s;
  1520.  
  1521.     s->defn_name = cmd->config_file->name;
  1522.     s->defn_line_number = cmd->config_file->line_number;
  1523.  
  1524.     old_end_token = cmd->end_token;
  1525.     cmd->end_token = end_virtualhost_section;
  1526.     cmd->server = s;
  1527.     errmsg = ap_srm_command_loop(cmd, s->lookup_defaults);
  1528.     cmd->server = main_server;
  1529.     if (errmsg == NULL) {
  1530.     errmsg = missing_endsection(cmd, 1);
  1531.     }
  1532.     cmd->end_token = old_end_token;
  1533.  
  1534.     if (s->srm_confname) {
  1535.     ap_process_resource_config(s, s->srm_confname, p, ptemp);
  1536.     }
  1537.  
  1538.     if (s->access_confname) {
  1539.     ap_process_resource_config(s, s->access_confname, p, ptemp);
  1540.     }
  1541.     
  1542.     if (errmsg == end_virtualhost_section) {
  1543.     return NULL;
  1544.     }
  1545.     return errmsg;
  1546. }
  1547.  
  1548. static const char *set_server_alias(cmd_parms *cmd, void *dummy,
  1549.                     const char *arg)
  1550. {
  1551.     if (!cmd->server->names) {
  1552.     return "ServerAlias only used in <VirtualHost>";
  1553.     }
  1554.     while (*arg) {
  1555.     char **item, *name = ap_getword_conf(cmd->pool, &arg);
  1556.     if (ap_is_matchexp(name)) {
  1557.         item = (char **)ap_push_array(cmd->server->wild_names);
  1558.     }
  1559.     else {
  1560.         item = (char **)ap_push_array(cmd->server->names);
  1561.     }
  1562.     *item = name;
  1563.     }
  1564.     return NULL;
  1565. }
  1566.  
  1567. static const char *add_module_command(cmd_parms *cmd, void *dummy, char *arg)
  1568. {
  1569.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1570.     if (err != NULL) {
  1571.         return err;
  1572.     }
  1573.  
  1574.     if (!ap_add_named_module(arg)) {
  1575.     return ap_pstrcat(cmd->pool, "Cannot add module via name '", arg, 
  1576.               "': not in list of loaded modules", NULL);
  1577.     }
  1578.     return NULL;
  1579. }
  1580.  
  1581. static const char *clear_module_list_command(cmd_parms *cmd, void *dummy)
  1582. {
  1583.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1584.     if (err != NULL) {
  1585.         return err;
  1586.     }
  1587.  
  1588.     ap_clear_module_list();
  1589.     return NULL;
  1590. }
  1591.  
  1592. static const char *set_server_string_slot(cmd_parms *cmd, void *dummy,
  1593.                       char *arg)
  1594. {
  1595.     /* This one's pretty generic... */
  1596.   
  1597.     int offset = (int)(long)cmd->info;
  1598.     char *struct_ptr = (char *)cmd->server;
  1599.     
  1600.     const char *err = ap_check_cmd_context(cmd, 
  1601.                        NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1602.     if (err != NULL) {
  1603.         return err;
  1604.     }
  1605.  
  1606.     *(char **)(struct_ptr + offset) = arg;
  1607.     return NULL;
  1608. }
  1609.  
  1610. static const char *server_type(cmd_parms *cmd, void *dummy, char *arg)
  1611. {
  1612.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1613.     if (err != NULL) {
  1614.         return err;
  1615.     }
  1616.  
  1617.     if (!strcasecmp(arg, "inetd")) {
  1618.         ap_standalone = 0;
  1619.     }
  1620.     else if (!strcasecmp(arg, "standalone")) {
  1621.         ap_standalone = 1;
  1622.     }
  1623.     else {
  1624.         return "ServerType must be either 'inetd' or 'standalone'";
  1625.     }
  1626.  
  1627.     return NULL;
  1628. }
  1629.  
  1630. static const char *server_port(cmd_parms *cmd, void *dummy, char *arg)
  1631. {
  1632.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1633.     int port;
  1634.  
  1635.     if (err != NULL) {
  1636.     return err;
  1637.     }
  1638.     port = atoi(arg);
  1639.     if (port <= 0 || port >= 65536) { /* 65536 == 1<<16 */
  1640.     return ap_pstrcat(cmd->temp_pool, "The port number \"", arg, 
  1641.               "\" is outside the appropriate range "
  1642.               "(i.e., 1..65535).", NULL);
  1643.     }
  1644.     cmd->server->port = port;
  1645.     return NULL;
  1646. }
  1647.  
  1648. static const char *set_signature_flag(cmd_parms *cmd, core_dir_config *d, 
  1649.                       char *arg)
  1650. {
  1651.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  1652.     if (err != NULL) {
  1653.         return err;
  1654.     }
  1655.  
  1656.     if (strcasecmp(arg, "On") == 0) {
  1657.     d->server_signature = srv_sig_on;
  1658.     }
  1659.     else if (strcasecmp(arg, "Off") == 0) {
  1660.         d->server_signature = srv_sig_off;
  1661.     }
  1662.     else if (strcasecmp(arg, "EMail") == 0) {
  1663.     d->server_signature = srv_sig_withmail;
  1664.     }
  1665.     else {
  1666.     return "ServerSignature: use one of: off | on | email";
  1667.     }
  1668.     return NULL;
  1669. }
  1670.  
  1671. static const char *set_send_buffer_size(cmd_parms *cmd, void *dummy, char *arg)
  1672. {
  1673.     int s = atoi(arg);
  1674.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1675.     if (err != NULL) {
  1676.         return err;
  1677.     }
  1678.  
  1679.     if (s < 512 && s != 0) {
  1680.         return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
  1681.     }
  1682.     cmd->server->send_buffer_size = s;
  1683.     return NULL;
  1684. }
  1685.  
  1686. static const char *set_user(cmd_parms *cmd, void *dummy, char *arg)
  1687. {
  1688. #ifdef WIN32
  1689.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, cmd->server,
  1690.          "User directive has no affect on Win32");
  1691.     cmd->server->server_uid = ap_user_id = 1;
  1692. #else
  1693.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1694.     if (err != NULL) {
  1695.         return err;
  1696.     }
  1697.  
  1698.     if (!cmd->server->is_virtual) {
  1699.     ap_user_name = arg;
  1700.     cmd->server->server_uid = ap_user_id = ap_uname2id(arg);
  1701.     }
  1702.     else {
  1703.         if (ap_suexec_enabled) {
  1704.         cmd->server->server_uid = ap_uname2id(arg);
  1705.     }
  1706.     else {
  1707.         cmd->server->server_uid = ap_user_id;
  1708.         fprintf(stderr,
  1709.             "Warning: User directive in <VirtualHost> "
  1710.             "requires SUEXEC wrapper.\n");
  1711.     }
  1712.     }
  1713. #if !defined (BIG_SECURITY_HOLE) && !defined (OS2)
  1714.     if (cmd->server->server_uid == 0) {
  1715.     fprintf(stderr,
  1716.         "Error:\tApache has not been designed to serve pages while\n"
  1717.         "\trunning as root.  There are known race conditions that\n"
  1718.         "\twill allow any local user to read any file on the system.\n"
  1719.         "\tShould you still desire to serve pages as root then\n"
  1720.         "\tadd -DBIG_SECURITY_HOLE to the EXTRA_CFLAGS line in your\n"
  1721.         "\tsrc/Configuration file and rebuild the server.  It is\n"
  1722.         "\tstrongly suggested that you instead modify the User\n"
  1723.         "\tdirective in your httpd.conf file to list a non-root\n"
  1724.         "\tuser.\n");
  1725.     exit (1);
  1726.     }
  1727. #endif
  1728. #endif /* WIN32 */
  1729.  
  1730.     return NULL;
  1731. }
  1732.  
  1733. static const char *set_group(cmd_parms *cmd, void *dummy, char *arg)
  1734. {
  1735.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1736.     if (err != NULL) {
  1737.         return err;
  1738.     }
  1739.  
  1740.     if (!cmd->server->is_virtual) {
  1741.     cmd->server->server_gid = ap_group_id = ap_gname2id(arg);
  1742.     }
  1743.     else {
  1744.         if (ap_suexec_enabled) {
  1745.         cmd->server->server_gid = ap_gname2id(arg);
  1746.     }
  1747.     else {
  1748.         cmd->server->server_gid = ap_group_id;
  1749.         fprintf(stderr,
  1750.             "Warning: Group directive in <VirtualHost> requires "
  1751.             "SUEXEC wrapper.\n");
  1752.     }
  1753.     }
  1754.  
  1755.     return NULL;
  1756. }
  1757.  
  1758. static const char *set_server_root(cmd_parms *cmd, void *dummy, char *arg) 
  1759. {
  1760.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1761.  
  1762.     if (err != NULL) {
  1763.         return err;
  1764.     }
  1765.  
  1766.     arg = ap_os_canonical_filename(cmd->pool, arg);
  1767.  
  1768.     if (!ap_is_directory(arg)) {
  1769.         return "ServerRoot must be a valid directory";
  1770.     }
  1771.     ap_cpystrn(ap_server_root, arg,
  1772.            sizeof(ap_server_root));
  1773.     return NULL;
  1774. }
  1775.  
  1776. static const char *set_timeout(cmd_parms *cmd, void *dummy, char *arg)
  1777. {
  1778.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1779.     if (err != NULL) {
  1780.         return err;
  1781.     }
  1782.  
  1783.     cmd->server->timeout = atoi(arg);
  1784.     return NULL;
  1785. }
  1786.  
  1787. static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy,
  1788.                       char *arg)
  1789. {
  1790.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1791.     if (err != NULL) {
  1792.         return err;
  1793.     }
  1794.  
  1795.     cmd->server->keep_alive_timeout = atoi(arg);
  1796.     return NULL;
  1797. }
  1798.  
  1799. static const char *set_keep_alive(cmd_parms *cmd, void *dummy, char *arg) 
  1800. {
  1801.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1802.     if (err != NULL) {
  1803.         return err;
  1804.     }
  1805.  
  1806.     /* We've changed it to On/Off, but used to use numbers
  1807.      * so we accept anything but "Off" or "0" as "On"
  1808.      */
  1809.     if (!strcasecmp(arg, "off") || !strcmp(arg, "0")) {
  1810.     cmd->server->keep_alive = 0;
  1811.     }
  1812.     else {
  1813.     cmd->server->keep_alive = 1;
  1814.     }
  1815.     return NULL;
  1816. }
  1817.  
  1818. static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy, char *arg) 
  1819. {
  1820.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1821.     if (err != NULL) {
  1822.         return err;
  1823.     }
  1824.  
  1825.     cmd->server->keep_alive_max = atoi(arg);
  1826.     return NULL;
  1827. }
  1828.  
  1829. static const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg) 
  1830. {
  1831.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1832.     if (err != NULL) {
  1833.         return err;
  1834.     }
  1835.  
  1836.     if (cmd->server->is_virtual) {
  1837.     return "PidFile directive not allowed in <VirtualHost>";
  1838.     }
  1839.     ap_pid_fname = arg;
  1840.     return NULL;
  1841. }
  1842.  
  1843. static const char *set_scoreboard(cmd_parms *cmd, void *dummy, char *arg) 
  1844. {
  1845.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1846.     if (err != NULL) {
  1847.         return err;
  1848.     }
  1849.  
  1850.     ap_scoreboard_fname = arg;
  1851.     return NULL;
  1852. }
  1853.  
  1854. static const char *set_lockfile(cmd_parms *cmd, void *dummy, char *arg) 
  1855. {
  1856.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1857.     if (err != NULL) {
  1858.         return err;
  1859.     }
  1860.  
  1861.     ap_lock_fname = arg;
  1862.     return NULL;
  1863. }
  1864.  
  1865. static const char *set_idcheck(cmd_parms *cmd, core_dir_config *d, int arg) 
  1866. {
  1867.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  1868.     if (err != NULL) {
  1869.         return err;
  1870.     }
  1871.  
  1872.     d->do_rfc1413 = arg != 0;
  1873.     return NULL;
  1874. }
  1875.  
  1876. static const char *set_hostname_lookups(cmd_parms *cmd, core_dir_config *d,
  1877.                     char *arg)
  1878. {
  1879.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  1880.     if (err != NULL) {
  1881.         return err;
  1882.     }
  1883.  
  1884.     if (!strcasecmp(arg, "on")) {
  1885.     d->hostname_lookups = HOSTNAME_LOOKUP_ON;
  1886.     }
  1887.     else if (!strcasecmp(arg, "off")) {
  1888.     d->hostname_lookups = HOSTNAME_LOOKUP_OFF;
  1889.     }
  1890.     else if (!strcasecmp(arg, "double")) {
  1891.     d->hostname_lookups = HOSTNAME_LOOKUP_DOUBLE;
  1892.     }
  1893.     else {
  1894.     return "parameter must be 'on', 'off', or 'double'";
  1895.     }
  1896.     return NULL;
  1897. }
  1898.  
  1899. static const char *set_serverpath(cmd_parms *cmd, void *dummy, char *arg) 
  1900. {
  1901.     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  1902.     if (err != NULL) {
  1903.         return err;
  1904.     }
  1905.  
  1906.     cmd->server->path = arg;
  1907.     cmd->server->pathlen = strlen(arg);
  1908.     return NULL;
  1909. }
  1910.  
  1911. static const char *set_content_md5(cmd_parms *cmd, core_dir_config *d, int arg)
  1912. {
  1913.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  1914.     if (err != NULL) {
  1915.         return err;
  1916.     }
  1917.  
  1918.     d->content_md5 = arg != 0;
  1919.     return NULL;
  1920. }
  1921.  
  1922. static const char *set_use_canonical_name(cmd_parms *cmd, core_dir_config *d, 
  1923.                       int arg)
  1924. {
  1925.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  1926.  
  1927.     if (err != NULL) {
  1928.     return err;
  1929.     }
  1930.     
  1931.     d->use_canonical_name = arg != 0;
  1932.     return NULL;
  1933. }
  1934.  
  1935. static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, char *arg) 
  1936. {
  1937. #ifdef WIN32
  1938.     fprintf(stderr, "WARNING: StartServers has no effect on Win32\n");
  1939. #else
  1940.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1941.     if (err != NULL) {
  1942.         return err;
  1943.     }
  1944.  
  1945.     ap_daemons_to_start = atoi(arg);
  1946. #endif
  1947.     return NULL;
  1948. }
  1949.  
  1950. static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, char *arg)
  1951. {
  1952.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1953.     if (err != NULL) {
  1954.         return err;
  1955.     }
  1956.  
  1957.     ap_daemons_min_free = atoi(arg);
  1958.     if (ap_daemons_min_free <= 0) {
  1959.        fprintf(stderr, "WARNING: detected MinSpareServers set to non-positive.\n");
  1960.        fprintf(stderr, "Resetting to 1 to avoid almost certain Apache failure.\n");
  1961.        fprintf(stderr, "Please read the documentation.\n");
  1962.        ap_daemons_min_free = 1;
  1963.     }
  1964.        
  1965.     return NULL;
  1966. }
  1967.  
  1968. static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, char *arg)
  1969. {
  1970.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1971.     if (err != NULL) {
  1972.         return err;
  1973.     }
  1974.  
  1975.     ap_daemons_max_free = atoi(arg);
  1976.     return NULL;
  1977. }
  1978.  
  1979. static const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg) 
  1980. {
  1981.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  1982.     if (err != NULL) {
  1983.         return err;
  1984.     }
  1985.  
  1986.     ap_daemons_limit = atoi(arg);
  1987.     if (ap_daemons_limit > HARD_SERVER_LIMIT) {
  1988.        fprintf(stderr, "WARNING: MaxClients of %d exceeds compile time limit "
  1989.            "of %d servers,\n", ap_daemons_limit, HARD_SERVER_LIMIT);
  1990.        fprintf(stderr, " lowering MaxClients to %d.  To increase, please "
  1991.            "see the\n", HARD_SERVER_LIMIT);
  1992.        fprintf(stderr, " HARD_SERVER_LIMIT define in src/include/httpd.h.\n");
  1993.        ap_daemons_limit = HARD_SERVER_LIMIT;
  1994.     } 
  1995.     else if (ap_daemons_limit < 1) {
  1996.     fprintf(stderr, "WARNING: Require MaxClients > 0, setting to 1\n");
  1997.     ap_daemons_limit = 1;
  1998.     }
  1999.     return NULL;
  2000. }
  2001.  
  2002. static const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg) 
  2003. {
  2004.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2005.     if (err != NULL) {
  2006.         return err;
  2007.     }
  2008.  
  2009.     ap_max_requests_per_child = atoi(arg);
  2010.     return NULL;
  2011. }
  2012.  
  2013. static const char *set_threads(cmd_parms *cmd, void *dummy, char *arg) {
  2014.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2015.     if (err != NULL) {
  2016.         return err;
  2017.     }
  2018.  
  2019.     ap_threads_per_child = atoi(arg);
  2020.     if (ap_threads_per_child > HARD_SERVER_LIMIT) {
  2021.         fprintf(stderr, "WARNING: ThreadsPerChild of %d exceeds compile time limit "
  2022.                 "of %d threads,\n", ap_threads_per_child, HARD_SERVER_LIMIT);
  2023.         fprintf(stderr, " lowering ThreadsPerChild to %d.  To increase, please "
  2024.                 "see the\n", HARD_SERVER_LIMIT);
  2025.         fprintf(stderr, " HARD_SERVER_LIMIT define in src/include/httpd.h.\n");
  2026.         ap_threads_per_child = HARD_SERVER_LIMIT;
  2027.     } 
  2028.     else if (ap_threads_per_child < 1) {
  2029.     fprintf(stderr, "WARNING: Require ThreadsPerChild > 0, setting to 1\n");
  2030.     ap_threads_per_child = 1;
  2031.     }
  2032.  
  2033.     return NULL;
  2034. }
  2035.  
  2036. static const char *set_excess_requests(cmd_parms *cmd, void *dummy, char *arg) 
  2037. {
  2038.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2039.     if (err != NULL) {
  2040.         return err;
  2041.     }
  2042.  
  2043.     ap_excess_requests_per_child = atoi(arg);
  2044.     return NULL;
  2045. }
  2046.  
  2047.  
  2048. #if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS)
  2049. static void set_rlimit(cmd_parms *cmd, struct rlimit **plimit, const char *arg,
  2050.                        const char * arg2, int type)
  2051. {
  2052.     char *str;
  2053.     struct rlimit *limit;
  2054.     /* If your platform doesn't define rlim_t then typedef it in ap_config.h */
  2055.     rlim_t cur = 0;
  2056.     rlim_t max = 0;
  2057.  
  2058.     *plimit = (struct rlimit *)ap_pcalloc(cmd->pool, sizeof(**plimit));
  2059.     limit = *plimit;
  2060.     if ((getrlimit(type, limit)) != 0)    {
  2061.     *plimit = NULL;
  2062.     ap_log_error(APLOG_MARK, APLOG_ERR, cmd->server,
  2063.              "%s: getrlimit failed", cmd->cmd->name);
  2064.     return;
  2065.     }
  2066.  
  2067.     if ((str = ap_getword_conf(cmd->pool, &arg))) {
  2068.     if (!strcasecmp(str, "max")) {
  2069.         cur = limit->rlim_max;
  2070.     }
  2071.     else {
  2072.         cur = atol(str);
  2073.     }
  2074.     }
  2075.     else {
  2076.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
  2077.              "Invalid parameters for %s", cmd->cmd->name);
  2078.     return;
  2079.     }
  2080.     
  2081.     if (arg2 && (str = ap_getword_conf(cmd->pool, &arg2))) {
  2082.     max = atol(str);
  2083.     }
  2084.  
  2085.     /* if we aren't running as root, cannot increase max */
  2086.     if (geteuid()) {
  2087.     limit->rlim_cur = cur;
  2088.     if (max) {
  2089.         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
  2090.              "Must be uid 0 to raise maximum %s", cmd->cmd->name);
  2091.     }
  2092.     }
  2093.     else {
  2094.         if (cur) {
  2095.         limit->rlim_cur = cur;
  2096.     }
  2097.         if (max) {
  2098.         limit->rlim_max = max;
  2099.     }
  2100.     }
  2101. }
  2102. #endif
  2103.  
  2104. #if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
  2105. static const char *no_set_limit(cmd_parms *cmd, core_dir_config *conf,
  2106.                 char *arg, char *arg2)
  2107. {
  2108.     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
  2109.         "%s not supported on this platform", cmd->cmd->name);
  2110.     return NULL;
  2111. }
  2112. #endif
  2113.  
  2114. #ifdef RLIMIT_CPU
  2115. static const char *set_limit_cpu(cmd_parms *cmd, core_dir_config *conf, 
  2116.                  char *arg, char *arg2)
  2117. {
  2118.     set_rlimit(cmd, &conf->limit_cpu, arg, arg2, RLIMIT_CPU);
  2119.     return NULL;
  2120. }
  2121. #endif
  2122.  
  2123. #if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
  2124. static const char *set_limit_mem(cmd_parms *cmd, core_dir_config *conf, 
  2125.                  char *arg, char * arg2)
  2126. {
  2127. #if defined(RLIMIT_AS)
  2128.     set_rlimit(cmd, &conf->limit_mem, arg, arg2 ,RLIMIT_AS);
  2129. #elif defined(RLIMIT_DATA)
  2130.     set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_DATA);
  2131. #elif defined(RLIMIT_VMEM)
  2132.     set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_VMEM);
  2133. #endif
  2134.     return NULL;
  2135. }
  2136. #endif
  2137.  
  2138. #ifdef RLIMIT_NPROC
  2139. static const char *set_limit_nproc(cmd_parms *cmd, core_dir_config *conf,  
  2140.                    char *arg, char * arg2)
  2141. {
  2142.     set_rlimit(cmd, &conf->limit_nproc, arg, arg2, RLIMIT_NPROC);
  2143.     return NULL;
  2144. }
  2145. #endif
  2146.  
  2147. static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg) 
  2148. {
  2149.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2150.     if (err != NULL) {
  2151.         return err;
  2152.     }
  2153.  
  2154.     ap_bind_address.s_addr = ap_get_virthost_addr(arg, NULL);
  2155.     return NULL;
  2156. }
  2157.  
  2158. static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips)
  2159. {
  2160.     listen_rec *new;
  2161.     char *ports;
  2162.     unsigned short port;
  2163.  
  2164.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2165.     if (err != NULL) {
  2166.         return err;
  2167.     }
  2168.  
  2169.     ports = strchr(ips, ':');
  2170.     if (ports != NULL) {
  2171.     if (ports == ips) {
  2172.         return "Missing IP address";
  2173.     }
  2174.     else if (ports[1] == '\0') {
  2175.         return "Address must end in :<port-number>";
  2176.     }
  2177.     *(ports++) = '\0';
  2178.     }
  2179.     else {
  2180.     ports = ips;
  2181.     }
  2182.  
  2183.     new=ap_pcalloc(cmd->pool, sizeof(listen_rec));
  2184.     new->local_addr.sin_family = AF_INET;
  2185.     if (ports == ips) { /* no address */
  2186.     new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  2187.     }
  2188.     else {
  2189.     new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL);
  2190.     }
  2191.     port = atoi(ports);
  2192.     if (!port) {
  2193.     return "Port must be numeric";
  2194.     }
  2195.     new->local_addr.sin_port = htons(port);
  2196.     new->fd = -1;
  2197.     new->used = 0;
  2198.     new->next = ap_listeners;
  2199.     ap_listeners = new;
  2200.     return NULL;
  2201. }
  2202.  
  2203. static const char *set_listenbacklog(cmd_parms *cmd, void *dummy, char *arg) 
  2204. {
  2205.     int b;
  2206.  
  2207.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2208.     if (err != NULL) {
  2209.         return err;
  2210.     }
  2211.  
  2212.     b = atoi(arg);
  2213.     if (b < 1) {
  2214.         return "ListenBacklog must be > 0";
  2215.     }
  2216.     ap_listenbacklog = b;
  2217.     return NULL;
  2218. }
  2219.  
  2220. static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg) 
  2221. {
  2222.     struct stat finfo;
  2223.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2224.     if (err != NULL) {
  2225.         return err;
  2226.     }
  2227.  
  2228.     arg = ap_server_root_relative(cmd->pool, arg);
  2229.     if ((stat(arg, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
  2230.     return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", arg, 
  2231.               " does not exist or is not a directory", NULL);
  2232.     }
  2233.     ap_cpystrn(ap_coredump_dir, arg, sizeof(ap_coredump_dir));
  2234.     return NULL;
  2235. }
  2236.  
  2237. static const char *include_config (cmd_parms *cmd, void *dummy, char *name)
  2238. {
  2239.     name = ap_server_root_relative(cmd->pool, name);
  2240.     
  2241.     ap_process_resource_config(cmd->server, name, cmd->pool, cmd->temp_pool);
  2242.  
  2243.     return NULL;
  2244. }
  2245.  
  2246. static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg) 
  2247. {
  2248.     char *str;
  2249.     
  2250.     const char *err = ap_check_cmd_context(cmd,
  2251.                        NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  2252.     if (err != NULL) {
  2253.         return err;
  2254.     }
  2255.  
  2256.     if ((str = ap_getword_conf(cmd->pool, &arg))) {
  2257.         if (!strcasecmp(str, "emerg")) {
  2258.         cmd->server->loglevel = APLOG_EMERG;
  2259.     }
  2260.     else if (!strcasecmp(str, "alert")) {
  2261.         cmd->server->loglevel = APLOG_ALERT;
  2262.     }
  2263.     else if (!strcasecmp(str, "crit")) {
  2264.         cmd->server->loglevel = APLOG_CRIT;
  2265.     }
  2266.     else if (!strcasecmp(str, "error")) {
  2267.         cmd->server->loglevel = APLOG_ERR;
  2268.     }
  2269.     else if (!strcasecmp(str, "warn")) {
  2270.         cmd->server->loglevel = APLOG_WARNING;
  2271.     }
  2272.     else if (!strcasecmp(str, "notice")) {
  2273.         cmd->server->loglevel = APLOG_NOTICE;
  2274.     }
  2275.     else if (!strcasecmp(str, "info")) {
  2276.         cmd->server->loglevel = APLOG_INFO;
  2277.     }
  2278.     else if (!strcasecmp(str, "debug")) {
  2279.         cmd->server->loglevel = APLOG_DEBUG;
  2280.     }
  2281.     else {
  2282.             return "LogLevel requires level keyword: one of "
  2283.                "emerg/alert/crit/error/warn/notice/info/debug";
  2284.     }
  2285.     }
  2286.     else {
  2287.         return "LogLevel requires level keyword";
  2288.     }
  2289.  
  2290.     return NULL;
  2291. }
  2292.  
  2293. API_EXPORT(const char *) ap_psignature(const char *prefix, request_rec *r)
  2294. {
  2295.     char sport[20];
  2296.     core_dir_config *conf;
  2297.  
  2298.     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
  2299.                            &core_module);
  2300.     if (conf->server_signature == srv_sig_off) {
  2301.     return "";
  2302.     }
  2303.  
  2304.     ap_snprintf(sport, sizeof sport, "%u", (unsigned) ap_get_server_port(r));
  2305.  
  2306.     if (conf->server_signature == srv_sig_withmail) {
  2307.     return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
  2308.               " Server at <A HREF=\"mailto:",
  2309.               r->server->server_admin, "\">",
  2310.               ap_get_server_name(r), "</A> Port ", sport,
  2311.               "</ADDRESS>\n", NULL);
  2312.     }
  2313.     return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
  2314.               " Server at ", ap_get_server_name(r), " Port ", sport,
  2315.               "</ADDRESS>\n", NULL);
  2316. }
  2317.  
  2318. /*
  2319.  * Load an authorisation realm into our location configuration, applying the
  2320.  * usual rules that apply to realms.
  2321.  */
  2322. static const char *set_authname(cmd_parms *cmd, void *mconfig, char *word1)
  2323. {
  2324.     core_dir_config *aconfig = (core_dir_config *)mconfig;
  2325.  
  2326.     aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
  2327.     return NULL;
  2328. }
  2329.  
  2330. #ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
  2331. static const char *set_bs2000_account(cmd_parms *cmd, void *dummy, char *name)
  2332. {
  2333.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2334.     if (err != NULL) {
  2335.         return err;
  2336.     }
  2337.  
  2338.     return os_set_account(cmd->pool, name);
  2339. }
  2340. #endif /*_OSD_POSIX*/
  2341.  
  2342. /*
  2343.  * Handle a request to include the server's OS platform in the Server
  2344.  * response header field (the ServerTokens directive).  Unfortunately
  2345.  * this requires a new global in order to communicate the setting back to
  2346.  * http_main so it can insert the information in the right place in the
  2347.  * string.
  2348.  */
  2349.  
  2350. static const char *set_serv_tokens(cmd_parms *cmd, void *dummy, char *arg) 
  2351. {
  2352.     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  2353.     if (err != NULL) {
  2354.         return err;
  2355.     }
  2356.  
  2357.     if (!strcasecmp(arg, "OS")) {
  2358.         ap_server_tokens = SrvTk_OS;
  2359.     }
  2360.     else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
  2361.         ap_server_tokens = SrvTk_MIN;
  2362.     }
  2363.     else {
  2364.         ap_server_tokens = SrvTk_FULL;
  2365.     }
  2366.     return NULL;
  2367. }
  2368.  
  2369. static const char *set_limit_req_line(cmd_parms *cmd, void *dummy, char *arg)
  2370. {
  2371.     const char *err = ap_check_cmd_context(cmd,
  2372.                                            NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  2373.     int lim;
  2374.  
  2375.     if (err != NULL) {
  2376.         return err;
  2377.     }
  2378.     lim = atoi(arg);
  2379.     if (lim < 0) {
  2380.         return ap_pstrcat(cmd->temp_pool, "LimitRequestLine \"", arg, 
  2381.                           "\" must be a non-negative integer", NULL);
  2382.     }
  2383.     if (lim > DEFAULT_LIMIT_REQUEST_LINE) {
  2384.         return ap_psprintf(cmd->temp_pool, "LimitRequestLine \"%s\" "
  2385.                            "must not exceed the precompiled maximum of %d",
  2386.                            arg, DEFAULT_LIMIT_REQUEST_LINE);
  2387.     }
  2388.     cmd->server->limit_req_line = lim;
  2389.     return NULL;
  2390. }
  2391.  
  2392. static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy,
  2393.                                            char *arg)
  2394. {
  2395.     const char *err = ap_check_cmd_context(cmd,
  2396.                                            NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  2397.     int lim;
  2398.  
  2399.     if (err != NULL) {
  2400.         return err;
  2401.     }
  2402.     lim = atoi(arg);
  2403.     if (lim < 0) {
  2404.         return ap_pstrcat(cmd->temp_pool, "LimitRequestFieldsize \"", arg, 
  2405.                           "\" must be a non-negative integer (0 = no limit)",
  2406.                           NULL);
  2407.     }
  2408.     if (lim > DEFAULT_LIMIT_REQUEST_FIELDSIZE) {
  2409.         return ap_psprintf(cmd->temp_pool, "LimitRequestFieldsize \"%s\" "
  2410.                           "must not exceed the precompiled maximum of %d",
  2411.                            arg, DEFAULT_LIMIT_REQUEST_FIELDSIZE);
  2412.     }
  2413.     cmd->server->limit_req_fieldsize = lim;
  2414.     return NULL;
  2415. }
  2416.  
  2417. static const char *set_limit_req_fields(cmd_parms *cmd, void *dummy, char *arg)
  2418. {
  2419.     const char *err = ap_check_cmd_context(cmd,
  2420.                                            NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  2421.     int lim;
  2422.  
  2423.     if (err != NULL) {
  2424.         return err;
  2425.     }
  2426.     lim = atoi(arg);
  2427.     if (lim < 0) {
  2428.         return ap_pstrcat(cmd->temp_pool, "LimitRequestFields \"", arg, 
  2429.                           "\" must be a non-negative integer (0 = no limit)",
  2430.                           NULL);
  2431.     }
  2432.     cmd->server->limit_req_fields = lim;
  2433.     return NULL;
  2434. }
  2435.  
  2436. static const char *set_limit_req_body(cmd_parms *cmd, core_dir_config *conf,
  2437.                                       char *arg) 
  2438. {
  2439.     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  2440.     if (err != NULL) {
  2441.         return err;
  2442.     }
  2443.  
  2444.     /* WTF: If strtoul is not portable, then write a replacement.
  2445.      *      Instead we have an idiotic define in httpd.h that prevents
  2446.      *      it from being used even when it is available. Sheesh.
  2447.      */
  2448.     conf->limit_req_body = (unsigned long)strtol(arg, (char **)NULL, 10);
  2449.     return NULL;
  2450. }
  2451.  
  2452. /* Note --- ErrorDocument will now work from .htaccess files.  
  2453.  * The AllowOverride of Fileinfo allows webmasters to turn it off
  2454.  */
  2455.  
  2456. static const command_rec core_cmds[] = {
  2457.  
  2458. /* Old access config file commands */
  2459.  
  2460. { "<Directory", dirsection, NULL, RSRC_CONF, RAW_ARGS,
  2461.   "Container for directives affecting resources located in the specified "
  2462.   "directories" },
  2463. { end_directory_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
  2464.   "Marks end of <Directory>" },
  2465. { "<Location", urlsection, NULL, RSRC_CONF, RAW_ARGS,
  2466.   "Container for directives affecting resources accessed through the "
  2467.   "specified URL paths" },
  2468. { end_location_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
  2469.   "Marks end of <Location>" },
  2470. { "<VirtualHost", virtualhost_section, NULL, RSRC_CONF, RAW_ARGS,
  2471.   "Container to map directives to a particular virtual host, takes one or "
  2472.   "more host addresses" },
  2473. { end_virtualhost_section, end_nested_section, NULL, RSRC_CONF, NO_ARGS,
  2474.   "Marks end of <VirtualHost>" },
  2475. { "<Files", filesection, NULL, OR_ALL, RAW_ARGS, "Container for directives "
  2476.   "affecting files matching specified patterns" },
  2477. { end_files_section, end_nested_section, NULL, OR_ALL, NO_ARGS,
  2478.   "Marks end of <Files>" },
  2479. { "<Limit", ap_limit_section, NULL, OR_ALL, RAW_ARGS, "Container for "
  2480.   "authentication directives when accessed using specified HTTP methods" },
  2481. { "</Limit>", endlimit_section, NULL, OR_ALL, NO_ARGS,
  2482.   "Marks end of <Limit>" },
  2483. { "<IfModule", start_ifmod, NULL, OR_ALL, TAKE1,
  2484.   "Container for directives based on existance of specified modules" },
  2485. { end_ifmodule_section, end_ifmod, NULL, OR_ALL, NO_ARGS,
  2486.   "Marks end of <IfModule>" },
  2487. { "<IfDefine", start_ifdefine, NULL, OR_ALL, TAKE1,
  2488.   "Container for directives based on existance of command line defines" },
  2489. { end_ifdefine_section, end_ifdefine, NULL, OR_ALL, NO_ARGS,
  2490.   "Marks end of <IfDefine>" },
  2491. { "<DirectoryMatch", dirsection, (void*)1, RSRC_CONF, RAW_ARGS,
  2492.   "Container for directives affecting resources located in the "
  2493.   "specified directories" },
  2494. { end_directorymatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
  2495.   "Marks end of <DirectoryMatch>" },
  2496. { "<LocationMatch", urlsection, (void*)1, RSRC_CONF, RAW_ARGS,
  2497.   "Container for directives affecting resources accessed through the "
  2498.   "specified URL paths" },
  2499. { end_locationmatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS,
  2500.   "Marks end of <LocationMatch>" },
  2501. { "<FilesMatch", filesection, (void*)1, OR_ALL, RAW_ARGS,
  2502.   "Container for directives affecting files matching specified patterns" },
  2503. { end_filesmatch_section, end_nested_section, NULL, OR_ALL, NO_ARGS,
  2504.   "Marks end of <FilesMatch>" },
  2505. { "AuthType", ap_set_string_slot,
  2506.   (void*)XtOffsetOf(core_dir_config, ap_auth_type), OR_AUTHCFG, TAKE1,
  2507.   "An HTTP authorization type (e.g., \"Basic\")" },
  2508. { "AuthName", set_authname, NULL, OR_AUTHCFG, TAKE1,
  2509.   "The authentication realm (e.g. \"Members Only\")" },
  2510. { "Require", require, NULL, OR_AUTHCFG, RAW_ARGS,
  2511.   "Selects which authenticated users or groups may access a protected space" },
  2512. { "Satisfy", satisfy, NULL, OR_AUTHCFG, TAKE1,
  2513.   "access policy if both allow and require used ('all' or 'any')" },    
  2514. #ifdef GPROF
  2515. { "GprofDir", set_gprof_dir, NULL, RSRC_CONF, TAKE1,
  2516.   "Directory to plop gmon.out files" },
  2517. #endif
  2518.  
  2519. /* Old resource config file commands */
  2520.   
  2521. { "AccessFileName", set_access_name, NULL, RSRC_CONF, RAW_ARGS,
  2522.   "Name(s) of per-directory config files (default: .htaccess)" },
  2523. { "DocumentRoot", set_document_root, NULL, RSRC_CONF, TAKE1,
  2524.   "Root directory of the document tree"  },
  2525. { "ErrorDocument", set_error_document, NULL, OR_FILEINFO, RAW_ARGS,
  2526.   "Change responses for HTTP errors" },
  2527. { "AllowOverride", set_override, NULL, ACCESS_CONF, RAW_ARGS,
  2528.   "Controls what groups of directives can be configured by per-directory "
  2529.   "config files" },
  2530. { "Options", set_options, NULL, OR_OPTIONS, RAW_ARGS,
  2531.   "Set a number of attributes for a given directory" },
  2532. { "DefaultType", ap_set_string_slot,
  2533.   (void*)XtOffsetOf (core_dir_config, ap_default_type),
  2534.   OR_FILEINFO, TAKE1, "the default MIME type for untypable files" },
  2535.  
  2536. /* Old server config file commands */
  2537.  
  2538. { "ServerType", server_type, NULL, RSRC_CONF, TAKE1,
  2539.   "'inetd' or 'standalone'"},
  2540. { "Port", server_port, NULL, RSRC_CONF, TAKE1, "A TCP port number"},
  2541. { "HostnameLookups", set_hostname_lookups, NULL, ACCESS_CONF|RSRC_CONF, TAKE1,
  2542.   "\"on\" to enable, \"off\" to disable reverse DNS lookups, or \"double\" to "
  2543.   "enable double-reverse DNS lookups" },
  2544. { "User", set_user, NULL, RSRC_CONF, TAKE1,
  2545.   "Effective user id for this server"},
  2546. { "Group", set_group, NULL, RSRC_CONF, TAKE1,
  2547.   "Effective group id for this server"},
  2548. { "ServerAdmin", set_server_string_slot,
  2549.   (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
  2550.   "The email address of the server administrator" },
  2551. { "ServerName", set_server_string_slot,
  2552.   (void *)XtOffsetOf (server_rec, server_hostname), RSRC_CONF, TAKE1,
  2553.   "The hostname of the server" },
  2554. { "ServerSignature", set_signature_flag, NULL, ACCESS_CONF|RSRC_CONF, TAKE1,
  2555.   "En-/disable server signature (on|off|email)" },
  2556. { "ServerRoot", set_server_root, NULL, RSRC_CONF, TAKE1,
  2557.   "Common directory of server-related files (logs, confs, etc.)" },
  2558. { "ErrorLog", set_server_string_slot,
  2559.   (void *)XtOffsetOf (server_rec, error_fname), RSRC_CONF, TAKE1,
  2560.   "The filename of the error log" },
  2561. { "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
  2562.     "A file for logging the server process ID"},
  2563. { "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
  2564.     "A file for Apache to maintain runtime process management information"},
  2565. { "LockFile", set_lockfile, NULL, RSRC_CONF, TAKE1,
  2566.     "The lockfile used when Apache needs to lock the accept() call"},
  2567. { "AccessConfig", set_server_string_slot,
  2568.   (void *)XtOffsetOf (server_rec, access_confname), RSRC_CONF, TAKE1,
  2569.   "The filename of the access config file" },
  2570. { "ResourceConfig", set_server_string_slot,
  2571.   (void *)XtOffsetOf (server_rec, srm_confname), RSRC_CONF, TAKE1,
  2572.   "The filename of the resource config file" },
  2573. { "ServerAlias", set_server_alias, NULL, RSRC_CONF, RAW_ARGS,
  2574.   "A name or names alternately used to access the server" },
  2575. { "ServerPath", set_serverpath, NULL, RSRC_CONF, TAKE1,
  2576.   "The pathname the server can be reached at" },
  2577. { "Timeout", set_timeout, NULL, RSRC_CONF, TAKE1, "Timeout duration (sec)" },
  2578. { "KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF, TAKE1,
  2579.   "Keep-Alive timeout duration (sec)"},
  2580. { "MaxKeepAliveRequests", set_keep_alive_max, NULL, RSRC_CONF, TAKE1,
  2581.   "Maximum number of Keep-Alive requests per connection, or 0 for infinite" },
  2582. { "KeepAlive", set_keep_alive, NULL, RSRC_CONF, TAKE1,
  2583.   "Whether persistent connections should be On or Off" },
  2584. { "IdentityCheck", set_idcheck, NULL, RSRC_CONF|ACCESS_CONF, FLAG,
  2585.   "Enable identd (RFC 1413) user lookups - SLOW" },
  2586. { "ContentDigest", set_content_md5, NULL, OR_OPTIONS,
  2587.   FLAG, "whether or not to send a Content-MD5 header with each request" },
  2588. { "UseCanonicalName", set_use_canonical_name, NULL,
  2589.   OR_OPTIONS, FLAG,
  2590.   "Whether or not to always use the canonical ServerName : Port when "
  2591.   "constructing URLs" },
  2592. { "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
  2593.   "Number of child processes launched at server startup" },
  2594. { "MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, TAKE1,
  2595.   "Minimum number of idle children, to handle request spikes" },
  2596. { "MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1,
  2597.   "Maximum number of idle children" },
  2598. { "MaxServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1,
  2599.   "Deprecated equivalent to MaxSpareServers" },
  2600. { "ServersSafetyLimit", set_server_limit, NULL, RSRC_CONF, TAKE1,
  2601.   "Deprecated equivalent to MaxClients" },
  2602. { "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
  2603.   "Maximum number of children alive at the same time" },
  2604. { "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
  2605.   "Maximum number of requests a particular child serves before dying." },
  2606. { "RLimitCPU",
  2607. #ifdef RLIMIT_CPU
  2608.   set_limit_cpu, (void*)XtOffsetOf(core_dir_config, limit_cpu),
  2609. #else
  2610.   no_set_limit, NULL,
  2611. #endif
  2612.   OR_ALL, TAKE12, "Soft/hard limits for max CPU usage in seconds" },
  2613. { "RLimitMEM",
  2614. #if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
  2615.   set_limit_mem, (void*)XtOffsetOf(core_dir_config, limit_mem),
  2616. #else
  2617.   no_set_limit, NULL,
  2618. #endif
  2619.   OR_ALL, TAKE12, "Soft/hard limits for max memory usage per process" },
  2620. { "RLimitNPROC",
  2621. #ifdef RLIMIT_NPROC
  2622.   set_limit_nproc, (void*)XtOffsetOf(core_dir_config, limit_nproc),
  2623. #else
  2624.   no_set_limit, NULL,
  2625. #endif
  2626.    OR_ALL, TAKE12, "soft/hard limits for max number of processes per uid" },
  2627. { "BindAddress", set_bind_address, NULL, RSRC_CONF, TAKE1,
  2628.   "'*', a numeric IP address, or the name of a host with a unique IP address"},
  2629. { "Listen", set_listener, NULL, RSRC_CONF, TAKE1,
  2630.   "A port number or a numeric IP address and a port number"},
  2631. { "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1,
  2632.   "Send buffer size in bytes"},
  2633. { "AddModule", add_module_command, NULL, RSRC_CONF, ITERATE,
  2634.   "The name of a module" },
  2635. { "ClearModuleList", clear_module_list_command, NULL, RSRC_CONF, NO_ARGS, 
  2636.   NULL },
  2637. { "ThreadsPerChild", set_threads, NULL, RSRC_CONF, TAKE1,
  2638.   "Number of threads a child creates" },
  2639. { "ExcessRequestsPerChild", set_excess_requests, NULL, RSRC_CONF, TAKE1,
  2640.   "Maximum number of requests a particular child serves after it is ready "
  2641.   "to die." },
  2642. { "ListenBacklog", set_listenbacklog, NULL, RSRC_CONF, TAKE1,
  2643.   "Maximum length of the queue of pending connections, as used by listen(2)" },
  2644. { "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
  2645.   "The location of the directory Apache changes to before dumping core" },
  2646. { "Include", include_config, NULL, (RSRC_CONF | ACCESS_CONF), TAKE1,
  2647.   "Name of the config file to be included" },
  2648. { "LogLevel", set_loglevel, NULL, RSRC_CONF, TAKE1,
  2649.   "Level of verbosity in error logging" },
  2650. { "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE1,
  2651.   "A numeric IP address:port, or the name of a host" },
  2652. #ifdef _OSD_POSIX
  2653. { "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1,
  2654.   "Name of server User's bs2000 logon account name" },
  2655. #endif
  2656. { "ServerTokens", set_serv_tokens, NULL, RSRC_CONF, TAKE1,
  2657.   "Determine tokens displayed in the Server: header - Min(imal), OS or Full" },
  2658. { "LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF, TAKE1,
  2659.   "Limit on maximum size of an HTTP request line"},
  2660. { "LimitRequestFieldsize", set_limit_req_fieldsize, NULL, RSRC_CONF, TAKE1,
  2661.   "Limit on maximum size of an HTTP request header field"},
  2662. { "LimitRequestFields", set_limit_req_fields, NULL, RSRC_CONF, TAKE1,
  2663.   "Limit (0 = unlimited) on max number of header fields in a request message"},
  2664. { "LimitRequestBody", set_limit_req_body,
  2665.   (void*)XtOffsetOf(core_dir_config, limit_req_body),
  2666.   OR_ALL, TAKE1,
  2667.   "Limit (in bytes) on maximum size of request message body" },
  2668. { NULL },
  2669. };
  2670.  
  2671. /*****************************************************************
  2672.  *
  2673.  * Core handlers for various phases of server operation...
  2674.  */
  2675.  
  2676. static int core_translate(request_rec *r)
  2677. {
  2678.     void *sconf = r->server->module_config;
  2679.     core_server_config *conf = ap_get_module_config(sconf, &core_module);
  2680.   
  2681.     if (r->proxyreq) {
  2682.         return HTTP_FORBIDDEN;
  2683.     }
  2684.     if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
  2685.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  2686.              "Invalid URI in request %s", r->the_request);
  2687.     return BAD_REQUEST;
  2688.     }
  2689.     
  2690.     if (r->server->path 
  2691.     && !strncmp(r->uri, r->server->path, r->server->pathlen)
  2692.     && (r->server->path[r->server->pathlen - 1] == '/'
  2693.         || r->uri[r->server->pathlen] == '/'
  2694.         || r->uri[r->server->pathlen] == '\0')) {
  2695.         r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
  2696.                  (r->uri + r->server->pathlen), NULL);
  2697.     }
  2698.     else {
  2699.     /*
  2700.          * Make sure that we do not mess up the translation by adding two
  2701.          * /'s in a row.  This happens under windows when the document
  2702.          * root ends with a /
  2703.          */
  2704.         if ((conf->ap_document_root[strlen(conf->ap_document_root)-1] == '/')
  2705.         && (*(r->uri) == '/')) {
  2706.         r->filename = ap_pstrcat(r->pool, conf->ap_document_root, r->uri+1,
  2707.                      NULL);
  2708.     }
  2709.     else {
  2710.         r->filename = ap_pstrcat(r->pool, conf->ap_document_root, r->uri,
  2711.                      NULL);
  2712.     }
  2713.     }
  2714.  
  2715.     return OK;
  2716. }
  2717.  
  2718. static int do_nothing(request_rec *r) { return OK; }
  2719.  
  2720. #ifdef USE_MMAP_FILES
  2721. struct mmap {
  2722.     void *mm;
  2723.     size_t length;
  2724. };
  2725.  
  2726. static void mmap_cleanup(void *mmv)
  2727. {
  2728.     struct mmap *mmd = mmv;
  2729.  
  2730.     munmap(mmd->mm, mmd->length);
  2731. }
  2732. #endif
  2733.  
  2734. /*
  2735.  * Default handler for MIME types without other handlers.  Only GET
  2736.  * and OPTIONS at this point... anyone who wants to write a generic
  2737.  * handler for PUT or POST is free to do so, but it seems unwise to provide
  2738.  * any defaults yet... So, for now, we assume that this will always be
  2739.  * the last handler called and return 405 or 501.
  2740.  */
  2741.  
  2742. static int default_handler(request_rec *r)
  2743. {
  2744.     core_dir_config *d =
  2745.       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
  2746.     int rangestatus, errstatus;
  2747.     FILE *f;
  2748. #ifdef USE_MMAP_FILES
  2749.     caddr_t mm;
  2750. #endif
  2751.  
  2752.     /* This handler has no use for a request body (yet), but we still
  2753.      * need to read and discard it if the client sent one.
  2754.      */
  2755.     if ((errstatus = ap_discard_request_body(r)) != OK) {
  2756.         return errstatus;
  2757.     }
  2758.  
  2759.     r->allowed |= (1 << M_GET) | (1 << M_OPTIONS);
  2760.  
  2761.     if (r->method_number == M_INVALID) {
  2762.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  2763.             "Invalid method in request %s", r->the_request);
  2764.     return NOT_IMPLEMENTED;
  2765.     }
  2766.     if (r->method_number == M_OPTIONS) {
  2767.         return ap_send_http_options(r);
  2768.     }
  2769.     if (r->method_number == M_PUT) {
  2770.         return METHOD_NOT_ALLOWED;
  2771.     }
  2772.  
  2773.     if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) {
  2774.     char *emsg;
  2775.  
  2776.     emsg = "File does not exist: ";
  2777.     if (r->path_info == NULL) {
  2778.         emsg = ap_pstrcat(r->pool, emsg, r->filename, NULL);
  2779.     }
  2780.     else {
  2781.         emsg = ap_pstrcat(r->pool, emsg, r->filename, r->path_info, NULL);
  2782.     }
  2783.     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, "%s", emsg);
  2784.     return HTTP_NOT_FOUND;
  2785.     }
  2786.     if (r->method_number != M_GET) {
  2787.         return METHOD_NOT_ALLOWED;
  2788.     }
  2789.     
  2790. #if defined(OS2) || defined(WIN32)
  2791.     /* Need binary mode for OS/2 */
  2792.     f = ap_pfopen(r->pool, r->filename, "rb");
  2793. #else
  2794.     f = ap_pfopen(r->pool, r->filename, "r");
  2795. #endif
  2796.  
  2797.     if (f == NULL) {
  2798.         ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  2799.              "file permissions deny server access: %s", r->filename);
  2800.         return FORBIDDEN;
  2801.     }
  2802.     
  2803.     ap_update_mtime(r, r->finfo.st_mtime);
  2804.     ap_set_last_modified(r);
  2805.     ap_set_etag(r);
  2806.     ap_table_setn(r->headers_out, "Accept-Ranges", "bytes");
  2807.     if (((errstatus = ap_meets_conditions(r)) != OK)
  2808.     || (errstatus = ap_set_content_length(r, r->finfo.st_size))) {
  2809.         return errstatus;
  2810.     }
  2811.  
  2812. #ifdef USE_MMAP_FILES
  2813.     ap_block_alarms();
  2814.     if ((r->finfo.st_size >= MMAP_THRESHOLD)
  2815.     && (!r->header_only || (d->content_md5 & 1))) {
  2816.     /* we need to protect ourselves in case we die while we've got the
  2817.       * file mmapped */
  2818.     mm = mmap(NULL, r->finfo.st_size, PROT_READ, MAP_PRIVATE,
  2819.           fileno(f), 0);
  2820.     if (mm == (caddr_t)-1) {
  2821.         ap_log_rerror(APLOG_MARK, APLOG_CRIT, r,
  2822.              "default_handler: mmap failed: %s", r->filename);
  2823.     }
  2824.     }
  2825.     else {
  2826.     mm = (caddr_t)-1;
  2827.     }
  2828.  
  2829.     if (mm == (caddr_t)-1) {
  2830.     ap_unblock_alarms();
  2831. #endif
  2832.  
  2833.     if (d->content_md5 & 1) {
  2834.         ap_table_setn(r->headers_out, "Content-MD5",
  2835.               ap_md5digest(r->pool, f));
  2836.     }
  2837.  
  2838.     rangestatus = ap_set_byterange(r);
  2839. #ifdef CHARSET_EBCDIC
  2840.     /* To make serving of "raw ASCII text" files easy (they serve faster 
  2841.      * since they don't have to be converted from EBCDIC), a new
  2842.      * "magic" type prefix was invented: text/x-ascii-{plain,html,...}
  2843.      * If we detect one of these content types here, we simply correct
  2844.      * the type to the real text/{plain,html,...} type. Otherwise, we
  2845.      * set a flag that translation is required later on.
  2846.      */
  2847.         ap_checkconv(r);
  2848. #endif /*CHARSET_EBCDIC*/
  2849.  
  2850.     ap_send_http_header(r);
  2851.     
  2852.     if (!r->header_only) {
  2853.         if (!rangestatus) {
  2854.         ap_send_fd(f, r);
  2855.         }
  2856.         else {
  2857.         long offset, length;
  2858.         while (ap_each_byterange(r, &offset, &length)) {
  2859.             fseek(f, offset, SEEK_SET);
  2860.             ap_send_fd_length(f, r, length);
  2861.         }
  2862.         }
  2863.     }
  2864.  
  2865. #ifdef USE_MMAP_FILES
  2866.     }
  2867.     else {
  2868.     struct mmap *mmd;
  2869.  
  2870.     mmd = ap_palloc(r->pool, sizeof(*mmd));
  2871.     mmd->mm = mm;
  2872.     mmd->length = r->finfo.st_size;
  2873.     ap_register_cleanup(r->pool, (void *)mmd, mmap_cleanup, mmap_cleanup);
  2874.     ap_unblock_alarms();
  2875.  
  2876.     if (d->content_md5 & 1) {
  2877.         AP_MD5_CTX context;
  2878.         
  2879.         ap_MD5Init(&context);
  2880.         ap_MD5Update(&context, (void *)mm, r->finfo.st_size);
  2881.         ap_table_setn(r->headers_out, "Content-MD5",
  2882.               ap_md5contextTo64(r->pool, &context));
  2883.     }
  2884.  
  2885.     rangestatus = ap_set_byterange(r);
  2886.     ap_send_http_header(r);
  2887.     
  2888.     if (!r->header_only) {
  2889.         if (!rangestatus) {
  2890.         ap_send_mmap(mm, r, 0, r->finfo.st_size);
  2891.         }
  2892.         else {
  2893.         long offset, length;
  2894.         while (ap_each_byterange(r, &offset, &length)) {
  2895.             ap_send_mmap(mm, r, offset, length);
  2896.         }
  2897.         }
  2898.     }
  2899.     }
  2900. #endif
  2901.  
  2902.     ap_pfclose(r->pool, f);
  2903.     return OK;
  2904. }
  2905.  
  2906. static const handler_rec core_handlers[] = {
  2907. { "*/*", default_handler },
  2908. { "default-handler", default_handler },
  2909. { NULL }
  2910. };
  2911.  
  2912. API_VAR_EXPORT module core_module = {
  2913.     STANDARD_MODULE_STUFF,
  2914.     NULL,            /* initializer */
  2915.     create_core_dir_config,    /* create per-directory config structure */
  2916.     merge_core_dir_configs,    /* merge per-directory config structures */
  2917.     create_core_server_config,    /* create per-server config structure */
  2918.     merge_core_server_configs,    /* merge per-server config structures */
  2919.     core_cmds,            /* command table */
  2920.     core_handlers,        /* handlers */
  2921.     core_translate,        /* translate_handler */
  2922.     NULL,            /* check_user_id */
  2923.     NULL,            /* check auth */
  2924.     do_nothing,            /* check access */
  2925.     do_nothing,            /* type_checker */
  2926.     NULL,            /* pre-run fixups */
  2927.     NULL,            /* logger */
  2928.     NULL,            /* header parser */
  2929.     NULL,            /* child_init */
  2930.     NULL,            /* child_exit */
  2931.     NULL            /* post_read_request */
  2932. };
  2933.