summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/.cvsignore14
-rw-r--r--server/.indent.pro54
-rw-r--r--server/Makefile.in69
-rw-r--r--server/buildmark.c67
-rw-r--r--server/config.c1763
-rw-r--r--server/config.m429
-rw-r--r--server/connection.c263
-rw-r--r--server/core.c3336
-rw-r--r--server/error_bucket.c106
-rw-r--r--server/gen_test_char.c128
-rw-r--r--server/gen_test_char.dsp90
-rw-r--r--server/gen_test_char.mak300
-rw-r--r--server/gen_uri_delims.c89
-rw-r--r--server/gen_uri_delims.dsp90
-rw-r--r--server/gen_uri_delims.mak203
-rw-r--r--server/listen.c390
-rw-r--r--server/log.c753
-rw-r--r--server/main.c464
-rw-r--r--server/mpm/.cvsignore2
-rw-r--r--server/mpm/MPM.NAMING13
-rw-r--r--server/mpm/Makefile.in4
-rw-r--r--server/mpm/beos/.cvsignore5
-rw-r--r--server/mpm/beos/Makefile.in5
-rw-r--r--server/mpm/beos/beos.c1122
-rw-r--r--server/mpm/beos/beos.h69
-rw-r--r--server/mpm/beos/config5.m47
-rw-r--r--server/mpm/beos/mpm.h77
-rw-r--r--server/mpm/beos/mpm_default.h149
-rw-r--r--server/mpm/config.m434
-rw-r--r--server/mpm/experimental/perchild/.cvsignore5
-rw-r--r--server/mpm/experimental/perchild/Makefile.in5
-rw-r--r--server/mpm/experimental/perchild/config5.m46
-rw-r--r--server/mpm/experimental/perchild/mpm.h91
-rw-r--r--server/mpm/experimental/perchild/mpm_default.h147
-rw-r--r--server/mpm/experimental/perchild/perchild.c1829
-rw-r--r--server/mpm/monitoring-services.txt94
-rw-r--r--server/mpm/perchild/.cvsignore5
-rw-r--r--server/mpm/perchild/Makefile.in5
-rw-r--r--server/mpm/perchild/config5.m46
-rw-r--r--server/mpm/perchild/mpm.h91
-rw-r--r--server/mpm/perchild/mpm_default.h147
-rw-r--r--server/mpm/perchild/perchild.c1829
-rw-r--r--server/mpm/prefork/.cvsignore5
-rw-r--r--server/mpm/prefork/Makefile.in5
-rw-r--r--server/mpm/prefork/config.m43
-rw-r--r--server/mpm/prefork/mpm.h80
-rw-r--r--server/mpm/prefork/mpm_default.h135
-rw-r--r--server/mpm/prefork/prefork.c1515
-rw-r--r--server/mpm/spmt_os2/.cvsignore5
-rw-r--r--server/mpm/spmt_os2/Makefile.in5
-rw-r--r--server/mpm/spmt_os2/config5.m45
-rw-r--r--server/mpm/spmt_os2/mpm.h74
-rw-r--r--server/mpm/spmt_os2/mpm_default.h123
-rw-r--r--server/mpm/spmt_os2/spmt_os2.c1322
-rw-r--r--server/mpm/threaded/.cvsignore5
-rw-r--r--server/mpm/threaded/Makefile.in5
-rw-r--r--server/mpm/threaded/config5.m45
-rw-r--r--server/mpm/threaded/mpm.h79
-rw-r--r--server/mpm/threaded/mpm_default.h154
-rw-r--r--server/mpm/threaded/threaded.c1450
-rw-r--r--server/mpm/winnt/Win9xConHook.c739
-rw-r--r--server/mpm/winnt/Win9xConHook.def10
-rw-r--r--server/mpm/winnt/Win9xConHook.dsp103
-rw-r--r--server/mpm/winnt/Win9xConHook.h99
-rw-r--r--server/mpm/winnt/mpm.h71
-rw-r--r--server/mpm/winnt/mpm_default.h135
-rw-r--r--server/mpm/winnt/mpm_winnt.c2114
-rw-r--r--server/mpm/winnt/mpm_winnt.h159
-rw-r--r--server/mpm/winnt/registry.c489
-rw-r--r--server/mpm/winnt/service.c1292
-rw-r--r--server/mpm_common.c344
-rw-r--r--server/protocol.c1176
-rw-r--r--server/request.c1133
-rw-r--r--server/rfc1413.c288
-rw-r--r--server/scoreboard.c340
-rw-r--r--server/util.c1907
-rw-r--r--server/util_cfgtree.c89
-rw-r--r--server/util_charset.c99
-rw-r--r--server/util_date.c306
-rw-r--r--server/util_debug.c120
-rw-r--r--server/util_ebcdic.c168
-rw-r--r--server/util_filter.c305
-rw-r--r--server/util_md5.c215
-rw-r--r--server/util_script.c652
-rw-r--r--server/util_uri.c359
-rw-r--r--server/util_xml.c134
-rw-r--r--server/vhost.c1017
87 files changed, 0 insertions, 32793 deletions
diff --git a/server/.cvsignore b/server/.cvsignore
deleted file mode 100644
index 88ac171b53..0000000000
--- a/server/.cvsignore
+++ /dev/null
@@ -1,14 +0,0 @@
-Makefile
-.deps
-.libs
-*.lo
-*.la
-uri_delims.h
-gen_uri_delims
-test_char.h
-gen_test_char
-*.mak
-exports.c
-Debug
-Release
-apache.exports
diff --git a/server/.indent.pro b/server/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/server/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/server/Makefile.in b/server/Makefile.in
deleted file mode 100644
index 24aef10277..0000000000
--- a/server/Makefile.in
+++ /dev/null
@@ -1,69 +0,0 @@
-
-TARGET_EXPORTS = apache.exports
-CLEAN_TARGETS = gen_test_char gen_uri_delims test_char.h uri_delims.h \
- $(TARGET_EXPORTS) ApacheCoreOS2.def
-EXTRACLEAN_TARGETS = exports.c
-
-SUBDIRS = mpm
-
-LTLIBRARY_NAME = libmain.la
-LTLIBRARY_SOURCES = \
- uri_delims.h test_char.h \
- config.c log.c main.c vhost.c util.c util_date.c \
- util_script.c util_uri.c util_md5.c util_cfgtree.c util_ebcdic.c \
- rfc1413.c connection.c listen.c \
- mpm_common.c util_charset.c util_debug.c util_xml.c \
- util_filter.c exports.c buildmark.c scoreboard.c \
- error_bucket.c protocol.c core.c request.c
-
-targets = delete-exports $(LTLIBRARY_NAME) $(CORE_IMPLIB_FILE)
-
-include $(top_srcdir)/build/rules.mk
-include $(top_srcdir)/build/library.mk
-
-gen_uri_delims_OBJECTS = gen_uri_delims.lo
-gen_uri_delims: $(gen_uri_delims_OBJECTS)
- $(LINK) $(EXTRA_LDFLAGS) $(gen_uri_delims_OBJECTS) $(EXTRA_LIBS)
-
-gen_test_char_OBJECTS = gen_test_char.lo util_debug.lo
-gen_test_char: $(gen_test_char_OBJECTS)
- $(LINK) $(EXTRA_LDFLAGS) $(gen_test_char_OBJECTS) $(EXTRA_LIBS)
-
-uri_delims.h: gen_uri_delims
- ./gen_uri_delims > uri_delims.h
-
-test_char.h: gen_test_char
- ./gen_test_char > test_char.h
-
-util_uri.lo: uri_delims.h
-util.lo: test_char.h
-
-EXPORT_FILES = ../srclib/apr/apr.exports ../srclib/apr-util/aprutil.exports \
- $(TARGET_EXPORTS)
-
-delete-exports:
- @if test -f $(TARGET_EXPORTS); then \
- headers="`find ../include/*.h -newer $(TARGET_EXPORTS)`" ; \
- if test -n "$$headers"; then \
- echo Found newer headers. Will rebuild $(TARGET_EXPORTS). ; \
- echo rm -f $(TARGET_EXPORTS) ; \
- rm -f $(TARGET_EXPORTS) ; \
- fi \
- fi
-
-
-$(TARGET_EXPORTS):
- $(AWK) -f $(top_srcdir)/srclib/apr/build/make_export.awk \
- $(top_srcdir)/include/*.h \
- $(top_srcdir)/os/$(OS_DIR)/*.h > $@
-
-exports.c: $(EXPORT_FILES)
- (cat $(EXPORT_FILES) | ../build/buildexports.sh ..) > $@
-
-# wtf does this have to be explicit????
-exports.lo: exports.c
-
-# Rule to make def file for OS/2 core dll
-ApacheCoreOS2.def: exports.c $(top_srcdir)/os/$(OS_DIR)/core_header.def
- cat $(top_srcdir)/os/$(OS_DIR)/core_header.def > $@
- $(CPP) $< $(ALL_CPPFLAGS) $(ALL_INCLUDES) | grep "ap_hack_" | sed -e 's/^.*[)]\(.*\);$$/ "\1"/' >> $@
diff --git a/server/buildmark.c b/server/buildmark.c
deleted file mode 100644
index b25783d097..0000000000
--- a/server/buildmark.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "ap_config.h"
-#include "httpd.h"
-
-#if defined(__DATE__) && defined(__TIME__)
-static const char server_built[] = __DATE__ " " __TIME__;
-#else
-static const char server_built[] = "unknown";
-#endif
-
-AP_DECLARE(const char *) ap_get_server_built()
-{
- return server_built;
-}
diff --git a/server/config.c b/server/config.c
deleted file mode 100644
index 689b347777..0000000000
--- a/server/config.c
+++ /dev/null
@@ -1,1763 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_config.c: once was auxillary functions for reading httpd's config
- * file and converting filenames into a namespace
- *
- * Rob McCool
- *
- * Wall-to-wall rewrite for Apache... commands which are part of the
- * server core can now be found next door in "http_core.c". Now contains
- * general command loop, and functions which do bookkeeping for the new
- * Apache config stuff (modules and configuration vectors).
- *
- * rst
- *
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_portable.h"
-#include "apr_file_io.h"
-
-#define APR_WANT_STDIO
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_protocol.h"
-#include "http_core.h"
-#include "http_log.h" /* for errors in parse_htaccess */
-#include "http_request.h" /* for default_handler (see invoke_handler) */
-#include "http_main.h"
-#include "http_vhost.h"
-#include "util_cfgtree.h"
-#include "mpm.h"
-
-
-AP_DECLARE_DATA const char *ap_server_argv0;
-
-AP_DECLARE_DATA const char *ap_server_root;
-
-AP_DECLARE_DATA apr_array_header_t *ap_server_pre_read_config;
-AP_DECLARE_DATA apr_array_header_t *ap_server_post_read_config;
-AP_DECLARE_DATA apr_array_header_t *ap_server_config_defines;
-
-AP_DECLARE_DATA ap_directive_t *ap_conftree;
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(header_parser)
- APR_HOOK_LINK(pre_config)
- APR_HOOK_LINK(post_config)
- APR_HOOK_LINK(open_logs)
- APR_HOOK_LINK(child_init)
- APR_HOOK_LINK(handler)
- APR_HOOK_LINK(quick_handler)
- APR_HOOK_LINK(optional_fn_retrieve)
-)
-
-AP_IMPLEMENT_HOOK_RUN_ALL(int,header_parser,
- (request_rec *r),(r),OK,DECLINED)
-AP_IMPLEMENT_HOOK_VOID(pre_config,
- (apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp),
- (pconf,plog,ptemp))
-AP_IMPLEMENT_HOOK_VOID(post_config,
- (apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp,
- server_rec *s),(pconf,plog,ptemp,s))
-AP_IMPLEMENT_HOOK_VOID(open_logs,
- (apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp,
- server_rec *s),(pconf,plog,ptemp,s))
-AP_IMPLEMENT_HOOK_VOID(child_init,
- (apr_pool_t *pchild, server_rec *s),(pchild,s))
-
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,handler,(request_rec *r),
- (r),DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,quick_handler,(request_rec *r),
- (r),DECLINED)
-
-AP_IMPLEMENT_HOOK_VOID(optional_fn_retrieve,(void),())
-
-/****************************************************************
- *
- * We begin with the functions which deal with the linked list
- * of modules which control just about all of the server operation.
- */
-
-/* total_modules is the number of modules that have been linked
- * into the server.
- */
-static int total_modules = 0;
-/* dynamic_modules is the number of modules that have been added
- * after the pre-loaded ones have been set up. It shouldn't be larger
- * than DYNAMIC_MODULE_LIMIT.
- */
-static int dynamic_modules = 0;
-AP_DECLARE_DATA module *ap_top_module = NULL;
-AP_DECLARE_DATA module **ap_loaded_modules=NULL;
-
-typedef int (*handler_func) (request_rec *);
-typedef void *(*dir_maker_func) (apr_pool_t *, char *);
-typedef void *(*merger_func) (apr_pool_t *, void *, void *);
-
-/* Dealing with config vectors. These are associated with per-directory,
- * per-server, and per-request configuration, and have a void* pointer for
- * each modules. The nature of the structure pointed to is private to the
- * module in question... the core doesn't (and can't) know. However, there
- * are defined interfaces which allow it to create instances of its private
- * per-directory and per-server structures, and to merge the per-directory
- * structures of a directory and its subdirectory (producing a new one in
- * which the defaults applying to the base directory have been properly
- * overridden).
- */
-
-static ap_conf_vector_t *create_empty_config(apr_pool_t *p)
-{
- void *conf_vector = apr_pcalloc(p, sizeof(void *) *
- (total_modules + DYNAMIC_MODULE_LIMIT));
- return conf_vector;
-}
-
-static ap_conf_vector_t *create_default_per_dir_config(apr_pool_t *p)
-{
- void **conf_vector = apr_pcalloc(p, sizeof(void *) *
- (total_modules + DYNAMIC_MODULE_LIMIT));
- module *modp;
-
- for (modp = ap_top_module; modp; modp = modp->next) {
- dir_maker_func df = modp->create_dir_config;
-
- if (df)
- conf_vector[modp->module_index] = (*df) (p, NULL);
- }
-
- return (ap_conf_vector_t *) conf_vector;
-}
-
-ap_conf_vector_t *ap_merge_per_dir_configs(apr_pool_t *p,
- ap_conf_vector_t *base,
- ap_conf_vector_t *new_conf)
-{
- void **conf_vector = apr_palloc(p, sizeof(void *) * total_modules);
- void **base_vector = (void **) base;
- void **new_vector = (void **) new_conf;
- module *modp;
-
- for (modp = ap_top_module; modp; modp = modp->next) {
- merger_func df = modp->merge_dir_config;
- int i = modp->module_index;
-
- if (df && new_vector[i])
- conf_vector[i] = (*df) (p, base_vector[i], new_vector[i]);
- else
- conf_vector[i] = new_vector[i] ? new_vector[i] : base_vector[i];
- }
-
- return (ap_conf_vector_t *) conf_vector;
-}
-
-static ap_conf_vector_t *create_server_config(apr_pool_t *p, server_rec *s)
-{
- void **conf_vector = apr_pcalloc(p, sizeof(void *) *
- (total_modules + DYNAMIC_MODULE_LIMIT));
- module *modp;
-
- for (modp = ap_top_module; modp; modp = modp->next) {
- if (modp->create_server_config)
- conf_vector[modp->module_index] = (*modp->create_server_config) (p, s);
- }
-
- return (ap_conf_vector_t *) conf_vector;
-}
-
-static void merge_server_configs(apr_pool_t *p, ap_conf_vector_t *base,
- ap_conf_vector_t *virt)
-{
- /* Can reuse the 'virt' vector for the spine of it, since we don't
- * have to deal with the moral equivalent of .htaccess files here...
- */
-
- void **base_vector = (void **) base;
- void **virt_vector = (void **) virt;
- module *modp;
-
- for (modp = ap_top_module; modp; modp = modp->next) {
- merger_func df = modp->merge_server_config;
- int i = modp->module_index;
-
- if (!virt_vector[i])
- virt_vector[i] = base_vector[i];
- else if (df)
- virt_vector[i] = (*df) (p, base_vector[i], virt_vector[i]);
- }
-}
-
-ap_conf_vector_t *ap_create_request_config(apr_pool_t *p)
-{
- return create_empty_config(p);
-}
-
-ap_conf_vector_t *ap_create_conn_config(apr_pool_t *p)
-{
- return create_empty_config(p);
-}
-
-AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_per_dir_config(apr_pool_t *p)
-{
- return create_empty_config(p);
-}
-
-int ap_invoke_handler(request_rec *r)
-{
- const char *handler;
- const char *p;
- char *p2;
- int result;
- char hbuf[MAX_STRING_LEN];
- const char *old_handler = r->handler;
-
- if (!r->handler) {
- handler = r->content_type ? r->content_type : ap_default_type(r);
- if ((p=ap_strchr_c(handler, ';')) != NULL) {
- apr_cpystrn(hbuf, handler, sizeof hbuf);
- p2 = hbuf+(handler-p);
- handler = hbuf;
- /* MIME type arguments */
- while (p2 > handler && p2[-1] == ' ')
- --p2; /* strip trailing spaces */
- *p2='\0';
- }
- r->handler = handler;
- }
-
- result = ap_run_handler(r);
-
- r->handler = old_handler;
-
- if (result == DECLINED && r->handler && r->filename) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "handler \"%s\" not found for: %s", r->handler, r->filename);
- }
- return result == DECLINED ? HTTP_INTERNAL_SERVER_ERROR : result;
-}
-
-AP_DECLARE(int) ap_method_is_limited(cmd_parms *cmd, const char *method) {
- int methnum;
- int i;
- char **xmethod;
-
- methnum = ap_method_number_of(method);
- /*
- * The simple case: a method hard-coded into Apache.
- */
- if (methnum != M_INVALID) {
- return (methnum & cmd->limited);
- }
- /*
- * Some extension method we don't know implicitly.
- */
- if ((cmd->limited_xmethods == NULL)
- || (cmd->limited_xmethods->nelts == 0)) {
- return 0;
- }
- xmethod = (char **) cmd->limited_xmethods->elts;
- for (i = 0; i < cmd->limited_xmethods->nelts; ++i) {
- if (strcmp(method, xmethod[i]) == 0) {
- return 1;
- }
- }
- return 0;
-}
-
-AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p)
-{
- if(m->register_hooks)
- {
- if(getenv("SHOW_HOOKS"))
- {
- printf("Registering hooks for %s\n",m->name);
- apr_debug_module_hooks=1;
- }
- apr_current_hooking_module=m->name;
- m->register_hooks(p);
- }
-}
-
-/* One-time setup for precompiled modules --- NOT to be done on restart */
-
-AP_DECLARE(void) ap_add_module(module *m, apr_pool_t *p)
-{
- /* This could be called from an AddModule httpd.conf command,
- * after the file has been linked and the module structure within it
- * teased out...
- */
-
- if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s: module \"%s\" is not compatible with this "
- "version of Apache.", ap_server_argv0, m->name);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Please contact the vendor for the correct version.");
- exit(1);
- }
-
- if (m->next == NULL) {
- m->next = ap_top_module;
- ap_top_module = m;
- }
- if (m->module_index == -1) {
- m->module_index = total_modules++;
- dynamic_modules++;
-
- if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s: module \"%s\" could not be loaded, because"
- " the dynamic", ap_server_argv0, m->name);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "module limit was reached. Please increase "
- "DYNAMIC_MODULE_LIMIT and recompile.");
- exit(1);
- }
- }
-
- /* Some C compilers put a complete path into __FILE__, but we want
- * only the filename (e.g. mod_includes.c). So check for path
- * components (Unix and DOS), and remove them.
- */
-
- if (ap_strrchr_c(m->name, '/'))
- m->name = 1 + ap_strrchr_c(m->name, '/');
- if (ap_strrchr_c(m->name, '\\'))
- m->name = 1 + ap_strrchr_c(m->name, '\\');
-
-#ifdef _OSD_POSIX /* __FILE__="*POSIX(/home/martin/apache/src/modules/standard/mod_info.c)" */
- /* We cannot fix the string in-place, because it's const */
- if (m->name[strlen(m->name)-1]==')') {
- char *tmp = strdup(m->name); /* FIXME:memory leak, albeit a small one */
- tmp[strlen(tmp)-1] = '\0';
- m->name = tmp;
- }
-#endif /*_OSD_POSIX*/
-
- /* FIXME: is this the right place to call this?
- * It doesn't appear to be
- */
- ap_register_hooks(m, p);
-}
-
-/*
- * remove_module undoes what add_module did. There are some caveats:
- * when the module is removed, its slot is lost so all the current
- * per-dir and per-server configurations are invalid. So we should
- * only ever call this function when you are invalidating almost
- * all our current data. I.e. when doing a restart.
- */
-
-AP_DECLARE(void) ap_remove_module(module *m)
-{
- module *modp;
-
- modp = ap_top_module;
- if (modp == m) {
- /* We are the top module, special case */
- ap_top_module = modp->next;
- m->next = NULL;
- }
- else {
- /* Not the top module, find use. When found modp will
- * point to the module _before_ us in the list
- */
-
- while (modp && modp->next != m) {
- modp = modp->next;
- }
- if (!modp) {
- /* Uh-oh, this module doesn't exist */
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
- "Cannot remove module %s: not found in module list",
- m->name);
- return;
- }
- /* Eliminate us from the module list */
- modp->next = modp->next->next;
- }
-
- m->module_index = -1; /* simulate being unloaded, should
- * be unnecessary */
- dynamic_modules--;
- total_modules--;
-}
-
-AP_DECLARE(void) ap_add_loaded_module(module *mod, apr_pool_t *p)
-{
- module **m;
-
- /*
- * Add module pointer to top of chained module list
- */
- ap_add_module(mod, p);
-
- /*
- * And module pointer to list of loaded modules
- *
- * Notes: 1. ap_add_module() would already complain if no more space
- * exists for adding a dynamically loaded module
- * 2. ap_add_module() accepts double inclusion, so we have
- * to accept this, too.
- */
- for (m = ap_loaded_modules; *m != NULL; m++)
- ;
- *m++ = mod;
- *m = NULL;
-}
-
-AP_DECLARE(void) ap_remove_loaded_module(module *mod)
-{
- module **m;
- module **m2;
- int done;
-
- /*
- * Remove module pointer from chained module list
- */
- ap_remove_module(mod);
-
- /*
- * Remove module pointer from list of loaded modules
- *
- * Note: 1. We cannot determine if the module was successfully
- * removed by ap_remove_module().
- * 2. We have not to complain explicity when the module
- * is not found because ap_remove_module() did it
- * for us already.
- */
- for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
- if (*m2 == mod && done == 0)
- done = 1;
- else
- *m++ = *m2;
- }
- *m = NULL;
-}
-
-AP_DECLARE(void) ap_setup_prelinked_modules(process_rec *process)
-{
- module **m;
- module **m2;
-
- apr_global_hook_pool=process->pconf;
-
- /*
- * Initialise total_modules variable and module indices
- */
- total_modules = 0;
- for (m = ap_preloaded_modules; *m != NULL; m++)
- (*m)->module_index = total_modules++;
-
- /*
- * Initialise list of loaded modules
- */
- ap_loaded_modules = (module **)apr_palloc(process->pool,
- sizeof(module *)*(total_modules+DYNAMIC_MODULE_LIMIT+1));
- if (ap_loaded_modules == NULL) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Ouch! Out of memory in ap_setup_prelinked_modules()!");
- }
- for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
- *m2++ = *m++;
- *m2 = NULL;
-
- /*
- * Initialize chain of linked (=activate) modules
- */
- for (m = ap_prelinked_modules; *m != NULL; m++)
- ap_add_module(*m, process->pconf);
-
- apr_sort_hooks();
-}
-
-AP_DECLARE(const char *) ap_find_module_name(module *m)
-{
- return m->name;
-}
-
-AP_DECLARE(module *) ap_find_linked_module(const char *name)
-{
- module *modp;
-
- for (modp = ap_top_module; modp; modp = modp->next) {
- if (strcmp(modp->name, name) == 0)
- return modp;
- }
- return NULL;
-}
-
-/* Add a named module. Returns 1 if module found, 0 otherwise. */
-AP_DECLARE(int) ap_add_named_module(const char *name, apr_pool_t *p)
-{
- module *modp;
- int i = 0;
-
- for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
- if (strcmp(modp->name, name) == 0) {
- /* Only add modules that are not already enabled. */
- if (modp->next == NULL) {
- ap_add_module(modp, p);
- }
- return 1;
- }
- }
-
- return 0;
-}
-
-/*****************************************************************
- *
- * Resource, access, and .htaccess config files now parsed by a common
- * command loop.
- *
- * Let's begin with the basics; parsing the line and
- * invoking the function...
- */
-
-static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
- void *mconfig, const char *args)
-{
- char *w, *w2, *w3;
- const char *errmsg;
-
- if ((parms->override & cmd->req_override) == 0)
- return apr_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
-
- parms->info = cmd->cmd_data;
- parms->cmd = cmd;
-
- switch (cmd->args_how) {
- case RAW_ARGS:
-#ifdef RESOLVE_ENV_PER_TOKEN
- args = ap_resolve_env(parms->pool,args);
-#endif
- return cmd->AP_RAW_ARGS(parms, mconfig, args);
-
- case NO_ARGS:
- if (*args != 0)
- return apr_pstrcat(parms->pool, cmd->name, " takes no arguments",
- NULL);
-
- return cmd->AP_NO_ARGS(parms, mconfig);
-
- case TAKE1:
- w = ap_getword_conf(parms->pool, &args);
-
- if (*w == '\0' || *args != 0)
- return apr_pstrcat(parms->pool, cmd->name, " takes one argument",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- return cmd->AP_TAKE1(parms, mconfig, w);
-
- case TAKE2:
- w = ap_getword_conf(parms->pool, &args);
- w2 = ap_getword_conf(parms->pool, &args);
-
- if (*w == '\0' || *w2 == '\0' || *args != 0)
- return apr_pstrcat(parms->pool, cmd->name, " takes two arguments",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- return cmd->AP_TAKE2(parms, mconfig, w, w2);
-
- case TAKE12:
-
- w = ap_getword_conf(parms->pool, &args);
- w2 = ap_getword_conf(parms->pool, &args);
-
- if (*w == '\0' || *args != 0)
- return apr_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- return cmd->AP_TAKE2(parms, mconfig, w, *w2 ? w2 : NULL);
-
- case TAKE3:
-
- w = ap_getword_conf(parms->pool, &args);
- w2 = ap_getword_conf(parms->pool, &args);
- w3 = ap_getword_conf(parms->pool, &args);
-
- if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
- return apr_pstrcat(parms->pool, cmd->name, " takes three arguments",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
-
- case TAKE23:
-
- w = ap_getword_conf(parms->pool, &args);
- w2 = ap_getword_conf(parms->pool, &args);
- w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
-
- if (*w == '\0' || *w2 == '\0' || *args != 0)
- return apr_pstrcat(parms->pool, cmd->name,
- " takes two or three arguments",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
-
- case TAKE123:
-
- w = ap_getword_conf(parms->pool, &args);
- w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
- w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
-
- if (*w == '\0' || *args != 0)
- return apr_pstrcat(parms->pool, cmd->name,
- " takes one, two or three arguments",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
-
- case TAKE13:
-
- w = ap_getword_conf(parms->pool, &args);
- w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
- w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
-
- if (*w == '\0' || (w2 && *w2 && !w3) || *args != 0)
- return apr_pstrcat(parms->pool, cmd->name,
- " takes one or three arguments",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- return cmd->AP_TAKE3(parms, mconfig, w, w2, w3);
-
- case ITERATE:
-
- while (*(w = ap_getword_conf(parms->pool, &args)) != '\0')
- {
- if ((errmsg = cmd->AP_TAKE1(parms, mconfig, w)))
- return errmsg;
- }
-
- return NULL;
-
- case ITERATE2:
-
- w = ap_getword_conf(parms->pool, &args);
-
- if (*w == '\0' || *args == 0)
- return apr_pstrcat(parms->pool, cmd->name,
- " requires at least two arguments",
- cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
-
- while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0')
- {
- if ((errmsg = cmd->AP_TAKE2(parms, mconfig, w, w2)))
- return errmsg;
- }
-
- return NULL;
-
- case FLAG:
-
- w = ap_getword_conf(parms->pool, &args);
-
- if (*w == '\0' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
- return apr_pstrcat(parms->pool, cmd->name, " must be On or Off",
- NULL);
-
- return cmd->AP_FLAG(parms, mconfig, strcasecmp(w, "off") != 0);
-
- default:
-
- return apr_pstrcat(parms->pool, cmd->name,
- " is improperly configured internally (server bug)",
- NULL);
- }
-}
-
-AP_CORE_DECLARE(const command_rec *) ap_find_command(const char *name, const command_rec *cmds)
-{
- while (cmds->name)
- if (!strcasecmp(name, cmds->name))
- return cmds;
- else
- ++cmds;
-
- return NULL;
-}
-
-AP_CORE_DECLARE(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod)
-{
- const command_rec *cmdp;
- module *modp;
-
- for (modp = *mod; modp; modp = modp->next)
- if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
- *mod = modp;
- return cmdp;
- }
-
- return NULL;
-}
-
-AP_CORE_DECLARE(void *) ap_set_config_vectors(server_rec *server,
- ap_conf_vector_t *section_vector,
- const char *section,
- module *mod, apr_pool_t *pconf)
-{
- void *section_config = ap_get_module_config(section_vector, mod);
- void *server_config = ap_get_module_config(server->module_config, mod);
-
- if (!section_config && mod->create_dir_config) {
- /* ### need to fix the create_dir_config functions' prototype... */
- section_config = (*mod->create_dir_config) (pconf, (char *)section);
- ap_set_module_config(section_vector, mod, section_config);
- }
-
- if (!server_config && mod->create_server_config) {
- server_config = (*mod->create_server_config) (pconf, server);
- ap_set_module_config(server->module_config, mod, server_config);
- }
-
- return section_config;
-}
-
-static const char *execute_now(char *cmd_line, const char *args, cmd_parms *parms,
- apr_pool_t *p, apr_pool_t *ptemp,
- ap_directive_t **sub_tree, ap_directive_t *parent);
-
-static const char * ap_build_config_sub(apr_pool_t *p, apr_pool_t *temp_pool,
- const char *l, cmd_parms *parms,
- ap_directive_t **current,
- ap_directive_t **curr_parent,
- ap_directive_t **conftree)
-{
- const char *args;
- char *cmd_name;
- ap_directive_t *newdir;
- module *mod = ap_top_module;
- const command_rec *cmd;
-
- if (*l == '#' || *l == '\0')
- return NULL;
-
-#if RESOLVE_ENV_PER_TOKEN
- args = l;
-#else
- args = ap_resolve_env(temp_pool, l);
-#endif
- cmd_name = ap_getword_conf(p, &args);
- if (*cmd_name == '\0') {
- /* Note: this branch should not occur. An empty line should have
- * triggered the exit further above.
- */
- return NULL;
- }
-
- newdir = apr_pcalloc(p, sizeof(ap_directive_t));
- newdir->filename = parms->config_file->name;
- newdir->line_num = parms->config_file->line_number;
- newdir->directive = cmd_name;
- newdir->args = apr_pstrdup(p, args);
-
- if ((cmd = ap_find_command_in_modules(cmd_name, &mod)) != NULL) {
- if (cmd->req_override & EXEC_ON_READ) {
- const char *retval;
- ap_directive_t *sub_tree = NULL;
-
- parms->err_directive = newdir;
- retval = execute_now(cmd_name, args, parms, p, temp_pool,
- &sub_tree, *curr_parent);
- if (*current) {
- (*current)->next = sub_tree;
- }
- else {
- (*current) = sub_tree;
- if (*curr_parent) {
- (*curr_parent)->first_child = (*current);
- }
- if (*current) {
- (*current)->parent = (*curr_parent);
- }
- }
- if (*current) {
- if (!*conftree) {
- /* Before walking *current to the end of the list,
- * set the head to *current.
- */
- *conftree = *current;
- }
- while ((*current)->next != NULL) {
- (*current) = (*current)->next;
- (*current)->parent = (*curr_parent);
- }
- }
- return retval;
- }
- }
-
- if (cmd_name[0] == '<') {
- if (cmd_name[1] != '/') {
- (*current) = ap_add_node(curr_parent, *current, newdir, 1);
- }
- else if (*curr_parent == NULL) {
- parms->err_directive = newdir;
- return apr_pstrcat(p, cmd_name,
- " without matching <", cmd_name + 2,
- " section", NULL);
- }
- else {
- char *bracket = cmd_name + strlen(cmd_name) - 1;
-
- if (*bracket != '>') {
- parms->err_directive = newdir;
- return apr_pstrcat(p, cmd_name,
- "> directive missing closing '>'", NULL);
- }
- *bracket = '\0';
- if (strcasecmp(cmd_name + 2,
- (*curr_parent)->directive + 1) != 0) {
- parms->err_directive = newdir;
- return apr_pstrcat(p, "Expected </",
- (*curr_parent)->directive + 1, "> but saw ",
- cmd_name, ">", NULL);
- }
- *bracket = '>';
-
- /* done with this section; move up a level */
- *current = *curr_parent;
- *curr_parent = (*current)->parent;
- }
- }
- else {
- *current = ap_add_node(curr_parent, *current, newdir, 0);
- }
-
- return NULL;
-}
-
-const char *ap_build_cont_config(apr_pool_t *p, apr_pool_t *temp_pool,
- cmd_parms *parms,
- ap_directive_t **current,
- ap_directive_t **curr_parent,
- char *orig_directive)
-{
- char l[MAX_STRING_LEN];
- char *bracket;
- const char *retval;
- ap_directive_t *sub_tree = NULL;
-
- bracket = apr_pstrcat(p, orig_directive + 1, ">", NULL);
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
- if (!memcmp(l, "</", 2) &&
- (strcasecmp(l + 2, bracket) == 0) &&
- (*curr_parent == NULL)) {
- break;
- }
- retval = ap_build_config_sub(p, temp_pool, l, parms, current,
- curr_parent, &sub_tree);
- if (retval != NULL)
- return retval;
- if (sub_tree == NULL && curr_parent != NULL) {
- sub_tree = *curr_parent;
- }
- if (sub_tree == NULL && current != NULL) {
- sub_tree = *current;
- }
- }
- *current = sub_tree;
- return NULL;
-}
-
-static const char *ap_walk_config_sub(const ap_directive_t *current,
- cmd_parms *parms,
- ap_conf_vector_t *section_vector)
-{
- module *mod = ap_top_module;
-
- while (1) {
- const command_rec *cmd;
-
- if (!(cmd = ap_find_command_in_modules(current->directive, &mod))) {
- parms->err_directive = current;
- return apr_pstrcat(parms->pool, "Invalid command '",
- current->directive,
- "', perhaps mis-spelled or defined by a module "
- "not included in the server configuration",
- NULL);
- }
- else {
- void *dir_config = ap_set_config_vectors(parms->server,
- section_vector,
- parms->path,
- mod,
- parms->pool);
- const char *retval;
-
- retval = invoke_cmd(cmd, parms, dir_config, current->args);
- if (retval == NULL) {
- return NULL;
- }
- if (strcmp(retval, DECLINE_CMD) != 0) {
- /* If the directive in error has already been set, don't
- * replace it. Otherwise, an error inside a container
- * will be reported as occuring on the first line of the
- * container.
- */
- if (!parms->err_directive) {
- parms->err_directive = current;
- }
- return retval;
- }
-
- mod = mod->next; /* Next time around, skip this one */
- }
- }
- /* NOTREACHED */
-}
-
-AP_DECLARE(const char *) ap_walk_config(ap_directive_t *current,
- cmd_parms *parms,
- ap_conf_vector_t *section_vector)
-{
- ap_conf_vector_t *oldconfig = parms->context;
-
- parms->context = section_vector;
-
- /* scan through all directives, executing each one */
- for (; current != NULL; current = current->next) {
- const char *errmsg;
-
- parms->directive = current;
-
- /* actually parse the command and execute the correct function */
- errmsg = ap_walk_config_sub(current, parms, section_vector);
- if (errmsg != NULL) {
- /* restore the context (just in case) */
- parms->context = oldconfig;
- return errmsg;
- }
- }
-
- parms->context = oldconfig;
- return NULL;
-}
-
-
-AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
- apr_pool_t *p, apr_pool_t *temp_pool,
- ap_directive_t **conftree)
-{
- ap_directive_t *current = *conftree;
- ap_directive_t *curr_parent = NULL;
- char l[MAX_STRING_LEN];
- const char *errmsg;
-
- if (current != NULL) {
- while (current->next) {
- current = current->next;
- }
- }
-
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
-
- errmsg = ap_build_config_sub(p, temp_pool, l, parms,
- &current, &curr_parent, conftree);
- if (errmsg != NULL)
- return errmsg;
-
- if (*conftree == NULL && curr_parent != NULL) {
- *conftree = curr_parent;
- }
- if (*conftree == NULL && current != NULL) {
- *conftree = current;
- }
- }
-
- if (curr_parent != NULL) {
- errmsg = "";
- while (curr_parent != NULL) {
- errmsg = apr_psprintf(p, "%s%s%s:%u: %s> was not closed.",
- errmsg,
- *errmsg == '\0' ? "" : APR_EOL_STR,
- curr_parent->filename,
- curr_parent->line_num,
- curr_parent->directive);
- curr_parent = curr_parent->parent;
- }
- return errmsg;
- }
-
- return NULL;
-}
-
-/*
- * Generic command functions...
- */
-
-AP_DECLARE_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
- void *struct_ptr,
- const char *arg)
-{
- /* This one's pretty generic... */
-
- int offset = (int) (long) cmd->info;
- *(const char **) ((char *)struct_ptr + offset) = arg;
- return NULL;
-}
-
-AP_DECLARE_NONSTD(const char *) ap_set_int_slot(cmd_parms *cmd,
- void *struct_ptr,
- const char *arg)
-{
- char *endptr;
- char *error_str = NULL;
- int offset = (int) (long) cmd->info;
-
- *(int *) ((char*)struct_ptr + offset) = strtol(arg, &endptr, 10);
-
- if ((*arg == '\0') || (*endptr != '\0')) {
- error_str = apr_psprintf(cmd->pool,
- "Invalid value for directive %s, expected integer",
- cmd->directive->directive);
- }
-
- return error_str;
-}
-
-AP_DECLARE_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
- void *struct_ptr,
- const char *arg_)
-{
- /* This one's pretty generic... */
- char *arg=apr_pstrdup(cmd->pool,arg_);
-
- int offset = (int) (long) cmd->info;
- ap_str_tolower(arg);
- *(char **) ((char *)struct_ptr + offset) = arg;
- return NULL;
-}
-
-AP_DECLARE_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
- void *struct_ptr_v, int arg)
-{
- /* This one's pretty generic too... */
-
- int offset = (int) (long) cmd->info;
- char *struct_ptr = (char *)struct_ptr_v;
- *(int *) (struct_ptr + offset) = arg ? 1 : 0;
- return NULL;
-}
-
-AP_DECLARE_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, void *struct_ptr,
- const char *arg)
-{
- /* Prepend server_root to relative arg.
- This allows .htaccess to be independent of server_root,
- so the server can be moved or mirrored with less pain. */
- char *p;
- int offset = (int) (long) cmd->info;
-#ifndef OS2
- arg = ap_os_canonical_filename(cmd->pool, arg);
-#endif
- if (ap_os_is_path_absolute(arg))
- p = apr_pstrdup(cmd->pool, arg);
- else
- p = ap_make_full_path(cmd->pool, ap_server_root, arg);
- *(char **) ((char*)struct_ptr + offset) = p;
- return NULL;
-}
-
-/*****************************************************************
- *
- * Reading whole config files...
- */
-
-static cmd_parms default_parms =
-{NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
-
-AP_DECLARE(const char *) ap_server_root_relative(apr_pool_t *p, const char *file)
-{
-#ifndef OS2
- file = ap_os_canonical_filename(p, file);
-#endif
- if(ap_os_is_path_absolute(file))
- return file;
- return ap_make_full_path(p, ap_server_root, file);
-}
-
-AP_DECLARE(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
-{
- char l[MAX_STRING_LEN];
- const char *args;
- char *cmd_name;
-
- while(!(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
-#if RESOLVE_ENV_PER_TOKEN
- args = l;
-#else
- args = ap_resolve_env(cmd->temp_pool, l);
-#endif
- cmd_name = ap_getword_conf(cmd->pool, &args);
- if (cmd_name[0] == '<') {
- if (cmd_name[1] == '/') {
- cmd_name[strlen(cmd_name) - 1] = '\0';
- if (strcasecmp(cmd_name + 2, directive + 1) != 0) {
- return apr_pstrcat(cmd->pool, "Expected </",
- directive + 1, "> but saw ",
- cmd_name, ">", NULL);
- }
- return NULL; /* found end of container */
- }
- else {
- const char *msg;
-
- if ((msg = ap_soak_end_container(cmd, cmd_name)) != NULL) {
- return msg;
- }
- }
- }
- }
- return apr_pstrcat(cmd->pool, "Expected </",
- directive + 1, "> before end of configuration",
- NULL);
-}
-
-static const char *execute_now(char *cmd_line, const char *args, cmd_parms *parms,
- apr_pool_t *p, apr_pool_t *ptemp,
- ap_directive_t **sub_tree, ap_directive_t *parent)
-{
- module *mod = ap_top_module;
- const command_rec *cmd;
-
- if (!(cmd = ap_find_command_in_modules(cmd_line, &mod))) {
- return apr_pstrcat(parms->pool, "Invalid command '",
- cmd_line,
- "', perhaps mis-spelled or defined by a module "
- "not included in the server configuration",
- NULL);
- }
- else {
- return invoke_cmd(cmd, parms, sub_tree, args);
- }
-}
-
-/* This structure and the following functions are needed for the
- * table-based config file reading. They are passed to the
- * cfg_open_custom() routine.
- */
-
-/* Structure to be passed to cfg_open_custom(): it contains an
- * index which is incremented from 0 to nelts on each call to
- * cfg_getline() (which in turn calls arr_elts_getstr())
- * and an apr_array_header_t pointer for the string array.
- */
-typedef struct {
- apr_array_header_t *array;
- int curr_idx;
-} arr_elts_param_t;
-
-
-/* arr_elts_getstr() returns the next line from the string array. */
-static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
-{
- arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
-
- /* End of array reached? */
- if (++arr_param->curr_idx > arr_param->array->nelts)
- return NULL;
-
- /* return the line */
- apr_cpystrn(buf, ((char **) arr_param->array->elts)[arr_param->curr_idx - 1], bufsiz);
-
- return buf;
-}
-
-
-/* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
-static int arr_elts_close(void *param)
-{
- arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
- arr_param->curr_idx = arr_param->array->nelts;
- return 0;
-}
-
-static void process_command_config(server_rec *s, apr_array_header_t *arr,
- ap_directive_t **conftree, apr_pool_t *p,
- apr_pool_t *ptemp)
-{
- const char *errmsg;
- cmd_parms parms;
- arr_elts_param_t arr_parms;
-
- arr_parms.curr_idx = 0;
- arr_parms.array = arr;
-
- parms = default_parms;
- parms.pool = p;
- parms.temp_pool = ptemp;
- parms.server = s;
- parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
-
- parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
- &arr_parms, NULL,
- arr_elts_getstr, arr_elts_close);
-
- errmsg = ap_build_config(&parms, p, ptemp, conftree);
- if (errmsg) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Syntax error in -C/-c directive:" APR_EOL_STR "%s",
- errmsg);
- exit(1);
- }
-
- ap_cfg_closefile(parms.config_file);
-}
-
-typedef struct {
- char *fname;
-} fnames;
-
-static int fname_alphasort(const void *fn1, const void *fn2)
-{
- const fnames *f1 = fn1;
- const fnames *f2 = fn2;
-
- return strcmp(f1->fname,f2->fname);
-}
-
-void ap_process_resource_config(server_rec *s, const char *fname,
- ap_directive_t **conftree, apr_pool_t *p,
- apr_pool_t *ptemp)
-{
- cmd_parms parms;
- apr_finfo_t finfo;
- const char *errmsg;
- ap_configfile_t *cfp;
-
- fname = ap_server_root_relative(p, fname);
-
- /* don't require conf/httpd.conf if we have a -C or -c switch */
- if ((ap_server_pre_read_config->nelts
- || ap_server_post_read_config->nelts)
- && !(strcmp(fname, ap_server_root_relative(p, SERVER_CONFIG_FILE)))) {
- if (apr_lstat(&finfo, fname, APR_FINFO_TYPE, p) != APR_SUCCESS)
- return;
- }
-
- /*
- * here we want to check if the candidate file is really a
- * directory, and most definitely NOT a symlink (to prevent
- * horrible loops). If so, let's recurse and toss it back
- * into the function.
- */
- if (ap_is_rdirectory(ptemp, fname)) {
- apr_dir_t *dirp;
- apr_finfo_t dirent;
- int current;
- apr_array_header_t *candidates = NULL;
- fnames *fnew;
- apr_status_t rv;
- char errmsg[120];
-
- /*
- * first course of business is to grok all the directory
- * entries here and store 'em away. Recall we need full pathnames
- * for this.
- */
- fprintf(stderr, "Processing config directory: %s\n", fname);
- rv = apr_dir_open(&dirp, fname, p);
- if (rv != APR_SUCCESS) {
- fprintf(stderr, "%s: could not open config directory %s: %s\n",
- ap_server_argv0, fname,
- apr_strerror(rv, errmsg, sizeof errmsg));
- exit(1);
- }
- candidates = apr_array_make(p, 1, sizeof(fnames));
- while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {
- /* strip out '.' and '..' */
- if (strcmp(dirent.name, ".") &&
- strcmp(dirent.name, "..")) {
- fnew = (fnames *) apr_array_push(candidates);
- fnew->fname = ap_make_full_path(p, fname, dirent.name);
- }
- }
- apr_dir_close(dirp);
- if (candidates->nelts != 0) {
- qsort((void *) candidates->elts, candidates->nelts,
- sizeof(fnames), fname_alphasort);
- /*
- * Now recurse these... we handle errors and subdirectories
- * via the recursion, which is nice
- */
- for (current = 0; current < candidates->nelts; ++current) {
- fnew = &((fnames *) candidates->elts)[current];
- fprintf(stderr, " Processing config file: %s\n", fnew->fname);
- ap_process_resource_config(s, fnew->fname, conftree, p, ptemp);
- }
- }
- return;
- }
-
- /* GCC's initialization extensions are soooo nice here... */
-
- parms = default_parms;
- parms.pool = p;
- parms.temp_pool = ptemp;
- parms.server = s;
- parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
-
- if (ap_pcfg_openfile(&cfp, p, fname) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s: could not open document config file %s",
- ap_server_argv0, fname);
- exit(1);
- }
-
- parms.config_file = cfp;
-
- errmsg = ap_build_config(&parms, p, ptemp, conftree);
-
- if (errmsg != NULL) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Syntax error on line %d of %s:",
- parms.err_directive->line_num,
- parms.err_directive->filename);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", errmsg);
- exit(1);
- }
-
- ap_cfg_closefile(cfp);
-}
-
-AP_DECLARE(void) ap_process_config_tree(server_rec *s,
- ap_directive_t *conftree,
- apr_pool_t *p, apr_pool_t *ptemp)
-{
- const char *errmsg;
- cmd_parms parms;
-
- parms = default_parms;
- parms.pool = p;
- parms.temp_pool = ptemp;
- parms.server = s;
- parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
- parms.limited = -1;
-
- errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
- if (errmsg) {
- ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, p,
- "Syntax error on line %d of %s:",
- parms.err_directive->line_num,
- parms.err_directive->filename);
- ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, p,
- "%s", errmsg);
- exit(1);
- }
-}
-
-int ap_parse_htaccess(ap_conf_vector_t **result, request_rec *r, int override,
- const char *d, const char *access_name)
-{
- ap_configfile_t *f = NULL;
- cmd_parms parms;
- char *filename = NULL;
- const struct htaccess_result *cache;
- struct htaccess_result *new;
- ap_conf_vector_t *dc = NULL;
- apr_status_t status;
-
- /* firstly, search cache */
- for (cache = r->htaccess; cache != NULL; cache = cache->next)
- if (cache->override == override && strcmp(cache->dir, d) == 0) {
- if (cache->htaccess != NULL)
- *result = cache->htaccess;
- return OK;
- }
-
- parms = default_parms;
- parms.override = override;
- parms.pool = r->pool;
- parms.temp_pool = r->pool;
- parms.server = r->server;
- parms.path = apr_pstrdup(r->pool, d);
-
- /* loop through the access names and find the first one */
-
- while (access_name[0]) {
- filename = ap_make_full_path(r->pool, d,
- ap_getword_conf(r->pool, &access_name));
- status = ap_pcfg_openfile(&f, r->pool, filename);
-
- if (status == APR_SUCCESS) {
- const char *errmsg;
- ap_directive_t *temptree = NULL;
-
- dc = ap_create_per_dir_config(r->pool);
-
- parms.config_file = f;
- errmsg = ap_build_config(&parms, r->pool, r->pool, &temptree);
- if (errmsg == NULL)
- errmsg = ap_walk_config(temptree, &parms, dc);
-
- ap_cfg_closefile(f);
-
- if (errmsg) {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, r,
- "%s: %s", filename, errmsg);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- *result = dc;
- break;
- } else {
- if (!APR_STATUS_IS_ENOENT(status)
- && !APR_STATUS_IS_ENOTDIR(status)) {
- ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r,
- "%s pcfg_openfile: unable to check htaccess file, "
- "ensure it is readable",
- filename);
- apr_table_setn(r->notes, "error-notes",
- "Server unable to read htaccess file, denying "
- "access to be safe");
- return HTTP_FORBIDDEN;
- }
- }
- }
-
- /* cache it */
- new = apr_palloc(r->pool, sizeof(struct htaccess_result));
- new->dir = parms.path;
- new->override = override;
- new->htaccess = dc;
-
- /* add to head of list */
- new->next = r->htaccess;
- r->htaccess = new;
-
- return OK;
-}
-
-AP_CORE_DECLARE(const char *) ap_init_virtual_host(apr_pool_t *p,
- const char *hostname,
- server_rec *main_server,
- server_rec **ps)
-{
- server_rec *s = (server_rec *) apr_pcalloc(p, sizeof(server_rec));
-
- /* TODO: this crap belongs in http_core */
- s->process = main_server->process;
- s->server_admin = NULL;
- s->server_hostname = NULL;
- s->error_fname = NULL;
- s->timeout = 0;
- s->keep_alive_timeout = 0;
- s->keep_alive = -1;
- s->keep_alive_max = -1;
- s->error_log = main_server->error_log;
- s->loglevel = main_server->loglevel;
- /* useful default, otherwise we get a port of 0 on redirects */
- s->port = main_server->port;
- s->next = NULL;
-
- s->is_virtual = 1;
- s->names = apr_array_make(p, 4, sizeof(char **));
- s->wild_names = apr_array_make(p, 4, sizeof(char **));
-
- s->module_config = create_empty_config(p);
- s->lookup_defaults = ap_create_per_dir_config(p);
-
- s->limit_req_line = main_server->limit_req_line;
- s->limit_req_fieldsize = main_server->limit_req_fieldsize;
- s->limit_req_fields = main_server->limit_req_fields;
-
- *ps = s;
-
- return ap_parse_vhost_addrs(p, hostname, s);
-}
-
-
-AP_DECLARE(void) ap_fixup_virtual_hosts(apr_pool_t *p, server_rec *main_server)
-{
- server_rec *virt;
-
- for (virt = main_server->next; virt; virt = virt->next) {
- merge_server_configs(p, main_server->module_config,
- virt->module_config);
-
- virt->lookup_defaults =
- ap_merge_per_dir_configs(p, main_server->lookup_defaults,
- virt->lookup_defaults);
-
- if (virt->server_admin == NULL)
- virt->server_admin = main_server->server_admin;
-
- if (virt->timeout == 0)
- virt->timeout = main_server->timeout;
-
- if (virt->keep_alive_timeout == 0)
- virt->keep_alive_timeout = main_server->keep_alive_timeout;
-
- if (virt->keep_alive == -1)
- virt->keep_alive = main_server->keep_alive;
-
- if (virt->keep_alive_max == -1)
- virt->keep_alive_max = main_server->keep_alive_max;
-
- /* XXX: this is really something that should be dealt with by a
- * post-config api phase */
- ap_core_reorder_directories(p, virt);
- }
- ap_core_reorder_directories(p, main_server);
-}
-
-/*****************************************************************
- *
- * Getting *everything* configured...
- */
-
-static void init_config_globals(apr_pool_t *p)
-{
- /* Global virtual host hash bucket pointers. Init to null. */
- ap_init_vhost_config(p);
-}
-
-static server_rec *init_server_config(process_rec *process, apr_pool_t *p)
-{
- apr_status_t rv;
- server_rec *s = (server_rec *) apr_pcalloc(p, sizeof(server_rec));
-
- apr_file_open_stderr(&s->error_log, p);
- s->process = process;
- s->port = 0;
- s->server_admin = DEFAULT_ADMIN;
- s->server_hostname = NULL;
- s->error_fname = DEFAULT_ERRORLOG;
- s->loglevel = DEFAULT_LOGLEVEL;
- s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
- s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
- s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
- s->timeout = DEFAULT_TIMEOUT;
- s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
- s->keep_alive_max = DEFAULT_KEEPALIVE;
- s->keep_alive = 1;
- s->next = NULL;
- s->addrs = apr_pcalloc(p, sizeof(server_addr_rec));
- /* NOT virtual host; don't match any real network interface */
- rv = apr_sockaddr_info_get(&s->addrs->host_addr,
- NULL, APR_INET, 0, 0, p);
- ap_assert(rv == APR_SUCCESS); /* otherwise: bug or no storage */
- s->addrs->host_port = 0; /* matches any port */
- s->addrs->virthost = ""; /* must be non-NULL */
- s->names = s->wild_names = NULL;
-
- s->module_config = create_server_config(p, s);
- s->lookup_defaults = create_default_per_dir_config(p);
-
- return s;
-}
-
-
-AP_DECLARE(server_rec*) ap_read_config(process_rec *process, apr_pool_t *ptemp,
- const char *confname,
- ap_directive_t **conftree)
-{
- apr_pool_t *p = process->pconf;
- server_rec *s = init_server_config(process, p);
-
- init_config_globals(p);
-
- /* All server-wide config files now have the SAME syntax... */
-
- process_command_config(s, ap_server_pre_read_config, conftree,
- p, ptemp);
-
- ap_process_resource_config(s, confname, conftree, p, ptemp);
-
- process_command_config(s, ap_server_post_read_config, conftree,
- p, ptemp);
-
- return s;
-}
-
-AP_DECLARE(void) ap_single_module_configure(apr_pool_t *p, server_rec *s,
- module *m)
-{
- if (m->create_server_config)
- ap_set_module_config(s->module_config, m,
- (*m->create_server_config)(p, s));
- if (m->create_dir_config)
- ap_set_module_config(s->lookup_defaults, m,
- (*m->create_dir_config)(p, NULL));
-}
-
-AP_DECLARE(void) ap_run_rewrite_args(process_rec *process)
-{
- module *m;
-
- for (m = ap_top_module; m; m = m->next)
- if (m->rewrite_args)
- (*m->rewrite_args) (process);
-}
-
-/********************************************************************
- * Configuration directives are restricted in terms of where they may
- * appear in the main configuration files and/or .htaccess files according
- * to the bitmask req_override in the command_rec structure.
- * If any of the overrides set in req_override are also allowed in the
- * context in which the command is read, then the command is allowed.
- * The context is determined as follows:
- *
- * inside *.conf --> override = (RSRC_CONF|OR_ALL)&~(OR_AUTHCFG|OR_LIMIT);
- * within <Directory> or <Location> --> override = OR_ALL|ACCESS_CONF;
- * within .htaccess --> override = AllowOverride for current directory;
- *
- * the result is, well, a rather confusing set of possibilities for when
- * a particular directive is allowed to be used. This procedure prints
- * in English where the given (pc) directive can be used.
- */
-static void show_overrides(const command_rec *pc, module *pm)
-{
- int n = 0;
-
- printf("\tAllowed in *.conf ");
- if ((pc->req_override & (OR_OPTIONS | OR_FILEINFO | OR_INDEXES)) ||
- ((pc->req_override & RSRC_CONF) &&
- ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT)))))
- printf("anywhere");
- else if (pc->req_override & RSRC_CONF)
- printf("only outside <Directory>, <Files> or <Location>");
- else
- printf("only inside <Directory>, <Files> or <Location>");
-
- /* Warn if the directive is allowed inside <Directory> or .htaccess
- * but module doesn't support per-dir configuration */
-
- if ((pc->req_override & (OR_ALL | ACCESS_CONF)) && !pm->create_dir_config)
- printf(" [no per-dir config]");
-
- if (pc->req_override & OR_ALL) {
- printf(" and in .htaccess\n\twhen AllowOverride");
-
- if ((pc->req_override & OR_ALL) == OR_ALL)
- printf(" isn't None");
- else {
- printf(" includes ");
-
- if (pc->req_override & OR_AUTHCFG) {
- if (n++)
- printf(" or ");
- printf("AuthConfig");
- }
- if (pc->req_override & OR_LIMIT) {
- if (n++)
- printf(" or ");
- printf("Limit");
- }
- if (pc->req_override & OR_OPTIONS) {
- if (n++)
- printf(" or ");
- printf("Options");
- }
- if (pc->req_override & OR_FILEINFO) {
- if (n++)
- printf(" or ");
- printf("FileInfo");
- }
- if (pc->req_override & OR_INDEXES) {
- if (n++)
- printf(" or ");
- printf("Indexes");
- }
- }
- }
- printf("\n");
-}
-
-/* Show the preloaded configuration directives, the help string explaining
- * the directive arguments, in what module they are handled, and in
- * what parts of the configuration they are allowed. Used for httpd -L.
- */
-AP_DECLARE(void) ap_show_directives(void)
-{
- const command_rec *pc;
- int n;
-
- for (n = 0; ap_loaded_modules[n]; ++n)
- for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
- printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
- if (pc->errmsg)
- printf("\t%s\n", pc->errmsg);
- show_overrides(pc, ap_loaded_modules[n]);
- }
-}
-
-/* Show the preloaded module names. Used for httpd -l. */
-AP_DECLARE(void) ap_show_modules(void)
-{
- int n;
-
- printf("Compiled in modules:\n");
- for (n = 0; ap_loaded_modules[n]; ++n)
- printf(" %s\n", ap_loaded_modules[n]->name);
-}
-
-AP_DECLARE(const char *) ap_show_mpm(void)
-{
- return MPM_NAME;
-}
diff --git a/server/config.m4 b/server/config.m4
deleted file mode 100644
index 761be95a53..0000000000
--- a/server/config.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-dnl ## Check for libraries
-
-AC_CHECK_LIB(nsl, gethostname, APR_ADDTO(LIBS,-lnsl))
-AC_CHECK_LIB(socket, socket, APR_ADDTO(LIBS,-lsocket))
-AC_CHECK_LIB(nsl, gethostbyaddr, APR_ADDTO(LIBS,-lnsl))
-
-dnl ## Check for header files
-
-AC_CHECK_HEADERS(bstring.h unistd.h)
-
-dnl ## Check for typedefs, structures, and compiler characteristics.
-
-AC_CACHE_CHECK([for tm_gmtoff in struct tm], ac_cv_struct_tm_gmtoff,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <$ac_cv_struct_tm>], [struct tm tm; tm.tm_gmtoff;],
- ac_cv_struct_tm_gmtoff=yes, ac_cv_struct_tm_gmtoff=no)])
-
-if test "$ac_cv_struct_tm_gmtoff" = "yes"; then
- AC_DEFINE(HAVE_GMTOFF,,
- [Define if struct tm has a tm_gmtoff member])
-fi
-
-dnl ## Check for library functions
-
-AC_CHECK_FUNCS(syslog)
-
-dnl Obsolete scoreboard code uses this.
- AC_CHECK_HEADERS(sys/times.h)
- AC_CHECK_FUNCS(times)
diff --git a/server/connection.c b/server/connection.c
deleted file mode 100644
index 297d4eef8e..0000000000
--- a/server/connection.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_connection.h"
-#include "http_request.h"
-#include "http_protocol.h"
-#include "ap_mpm.h"
-#include "mpm_default.h"
-#include "http_config.h"
-#include "http_vhost.h"
-#include "scoreboard.h"
-#include "http_log.h"
-#include "util_filter.h"
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(pre_connection)
- APR_HOOK_LINK(process_connection)
-)
-
-AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c),(c),OK,DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,process_connection,(conn_rec *c),(c),DECLINED)
-
-/*
- * More machine-dependent networking gooo... on some systems,
- * you've got to be *really* sure that all the packets are acknowledged
- * before closing the connection, since the client will not be able
- * to see the last response if their TCP buffer is flushed by a RST
- * packet from us, which is what the server's TCP stack will send
- * if it receives any request data after closing the connection.
- *
- * In an ideal world, this function would be accomplished by simply
- * setting the socket option SO_LINGER and handling it within the
- * server's TCP stack while the process continues on to the next request.
- * Unfortunately, it seems that most (if not all) operating systems
- * block the server process on close() when SO_LINGER is used.
- * For those that don't, see USE_SO_LINGER below. For the rest,
- * we have created a home-brew lingering_close.
- *
- * Many operating systems tend to block, puke, or otherwise mishandle
- * calls to shutdown only half of the connection. You should define
- * NO_LINGCLOSE in ap_config.h if such is the case for your system.
- */
-#ifndef MAX_SECS_TO_LINGER
-#define MAX_SECS_TO_LINGER 30
-#endif
-
-#ifdef USE_SO_LINGER
-#define NO_LINGCLOSE /* The two lingering options are exclusive */
-
-static void sock_enable_linger(int s)
-{
- struct linger li;
-
- li.l_onoff = 1;
- li.l_linger = MAX_SECS_TO_LINGER;
-
- if (setsockopt(s, SOL_SOCKET, SO_LINGER,
- (char *) &li, sizeof(struct linger)) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
- "setsockopt: (SO_LINGER)");
- /* not a fatal error */
- }
-}
-
-#else
-#define sock_enable_linger(s) /* NOOP */
-#endif /* USE_SO_LINGER */
-
-AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c)
-{
- apr_bucket_brigade *bb;
- apr_bucket *b;
-
- bb = apr_brigade_create(c->pool);
- b = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(c->output_filters, bb);
-}
-
-/* we now proceed to read from the client until we get EOF, or until
- * MAX_SECS_TO_LINGER has passed. the reasons for doing this are
- * documented in a draft:
- *
- * http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt
- *
- * in a nutshell -- if we don't make this effort we risk causing
- * TCP RST packets to be sent which can tear down a connection before
- * all the response data has been sent to the client.
- */
-#define SECONDS_TO_LINGER 2
-void ap_lingering_close(conn_rec *c)
-{
- char dummybuf[512];
- apr_size_t nbytes = sizeof(dummybuf);
- apr_status_t rc;
- apr_int32_t timeout;
- apr_int32_t total_linger_time = 0;
-
-#ifdef NO_LINGCLOSE
- ap_flush_conn(c); /* just close it */
- apr_socket_close(c->client_socket);
- return;
-#endif
-
- /* Close the connection, being careful to send out whatever is still
- * in our buffers. If possible, try to avoid a hard close until the
- * client has ACKed our FIN and/or has stopped sending us data.
- */
-
- /* Send any leftover data to the client, but never try to again */
- ap_flush_conn(c);
-
- if (c->aborted) {
- apr_socket_close(c->client_socket);
- return;
- }
-
- /* Shut down the socket for write, which will send a FIN
- * to the peer.
- */
-
- if (apr_shutdown(c->client_socket, APR_SHUTDOWN_WRITE) != APR_SUCCESS ||
- c->aborted) {
- apr_socket_close(c->client_socket);
- return;
- }
-
- /* Read all data from the peer until we reach "end-of-file" (FIN
- * from peer) or we've exceeded our overall timeout. If the client does
- * not send us bytes within 2 seconds (a value pulled from Apache 1.3
- * which seems to work well), close the connection.
- */
- timeout = SECONDS_TO_LINGER * APR_USEC_PER_SEC;
- apr_setsocketopt(c->client_socket, APR_SO_TIMEOUT, timeout);
- for (;;) {
- nbytes = sizeof(dummybuf);
- rc = apr_recv(c->client_socket, dummybuf, &nbytes);
- if (rc != APR_SUCCESS || nbytes == 0) break;
-
- total_linger_time += SECONDS_TO_LINGER;
- if (total_linger_time >= MAX_SECS_TO_LINGER) {
- break;
- }
- }
-
- apr_socket_close(c->client_socket);
-}
-
-AP_CORE_DECLARE(void) ap_process_connection(conn_rec *c)
-{
- ap_update_vhost_given_ip(c);
-
- ap_run_pre_connection(c);
-
- ap_run_process_connection(c);
-
-}
-
-/* Clearly some of this stuff doesn't belong in a generalised connection
- structure, but for now...
-*/
-
-conn_rec *ap_new_connection(apr_pool_t *p, server_rec *server,
- apr_socket_t *inout, long id)
-{
- conn_rec *conn = (conn_rec *) apr_pcalloc(p, sizeof(conn_rec));
- apr_status_t rv;
-
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(id),
- SERVER_BUSY_READ, (request_rec *) NULL);
-
- /* Got a connection structure, so initialize what fields we can
- * (the rest are zeroed out by pcalloc).
- */
-
- conn->conn_config=ap_create_conn_config(p);
- conn->notes = apr_table_make(p, 5);
-
- conn->pool = p;
- if ((rv = apr_socket_addr_get(&conn->local_addr, APR_LOCAL, inout))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_INFO, rv, server,
- "apr_socket_addr_get(APR_LOCAL)");
- apr_socket_close(inout);
- return NULL;
- }
- apr_sockaddr_ip_get(&conn->local_ip, conn->local_addr);
- if ((rv = apr_socket_addr_get(&conn->remote_addr, APR_REMOTE, inout))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_INFO, rv, server,
- "apr_socket_addr_get(APR_REMOTE)");
- apr_socket_close(inout);
- return NULL;
- }
- apr_sockaddr_ip_get(&conn->remote_ip, conn->remote_addr);
- conn->base_server = server;
- conn->client_socket = inout;
-
- conn->id = id;
-
- return conn;
-}
diff --git a/server/core.c b/server/core.c
deleted file mode 100644
index 092eb62f09..0000000000
--- a/server/core.c
+++ /dev/null
@@ -1,3336 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-#include "apr_fnmatch.h"
-#include "apr_thread_proc.h" /* for RLIMIT stuff */
-
-#define APR_WANT_IOVEC
-#define APR_WANT_STRFUNC
-#define APR_WANT_MEMFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_protocol.h" /* For index_of_response(). Grump. */
-#include "http_request.h"
-#include "http_vhost.h"
-#include "http_main.h" /* For the default_handler below... */
-#include "http_log.h"
-#include "rfc1413.h"
-#include "util_md5.h"
-#include "http_connection.h"
-#include "apr_buckets.h"
-#include "util_filter.h"
-#include "util_ebcdic.h"
-#include "mpm.h"
-
-#include "mod_core.h"
-
-
-/* LimitXMLRequestBody handling */
-#define AP_LIMIT_UNSET ((long) -1)
-#define AP_DEFAULT_LIMIT_XML_BODY ((size_t)1000000)
-
-#define AP_MIN_SENDFILE_BYTES (256)
-
-/* Server core module... This module provides support for really basic
- * server operations, including options and commands which control the
- * operation of other modules. Consider this the bureaucracy module.
- *
- * The core module also defines handlers, etc., do handle just enough
- * to allow a server with the core module ONLY to actually serve documents
- * (though it slaps DefaultType on all of 'em); this was useful in testing,
- * but may not be worth preserving.
- *
- * This file could almost be mod_core.c, except for the stuff which affects
- * the http_conf_globals.
- */
-
-static void *create_core_dir_config(apr_pool_t *a, char *dir)
-{
- core_dir_config *conf;
-
- conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
- if (!dir || dir[strlen(dir) - 1] == '/') {
- conf->d = dir;
- }
- else if (strncmp(dir, "proxy:", 6) == 0) {
- conf->d = apr_pstrdup(a, dir);
- }
- else {
- conf->d = apr_pstrcat(a, dir, "/", NULL);
- }
- conf->d_is_fnmatch = conf->d ? (apr_is_fnmatch(conf->d) != 0) : 0;
- conf->d_components = conf->d ? ap_count_dirs(conf->d) : 0;
-
- conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
- conf->opts_add = conf->opts_remove = OPT_NONE;
- conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
-
- conf->content_md5 = 2;
-
- conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
-
- conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
- conf->do_rfc1413 = DEFAULT_RFC1413 | 2; /* set bit 1 to indicate default */
- conf->satisfy = SATISFY_NOSPEC;
-
-#ifdef RLIMIT_CPU
- conf->limit_cpu = NULL;
-#endif
-#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
- conf->limit_mem = NULL;
-#endif
-#ifdef RLIMIT_NPROC
- conf->limit_nproc = NULL;
-#endif
-
- conf->limit_req_body = 0;
- conf->limit_xml_body = AP_LIMIT_UNSET;
- conf->sec = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
-#ifdef WIN32
- conf->script_interpreter_source = INTERPRETER_SOURCE_UNSET;
-#endif
-
- conf->server_signature = srv_sig_unset;
-
- conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
- conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
-
- conf->output_filters = apr_array_make(a, 2, sizeof(void *));
- conf->input_filters = apr_array_make(a, 2, sizeof(void *));
- return (void *)conf;
-}
-
-static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
-{
- core_dir_config *base = (core_dir_config *)basev;
- core_dir_config *new = (core_dir_config *)newv;
- core_dir_config *conf;
- int i;
-
- conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
- memcpy((char *)conf, (const char *)base, sizeof(core_dir_config));
- if (base->response_code_strings) {
- conf->response_code_strings =
- apr_palloc(a, sizeof(*conf->response_code_strings)
- * RESPONSE_CODES);
- memcpy(conf->response_code_strings, base->response_code_strings,
- sizeof(*conf->response_code_strings) * RESPONSE_CODES);
- }
-
- conf->d = new->d;
- conf->d_is_fnmatch = new->d_is_fnmatch;
- conf->d_components = new->d_components;
- conf->r = new->r;
-
- if (new->opts & OPT_UNSET) {
- /* there was no explicit setting of new->opts, so we merge
- * preserve the invariant (opts_add & opts_remove) == 0
- */
- conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
- conf->opts_remove = (conf->opts_remove & ~new->opts_add)
- | new->opts_remove;
- conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
- if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
- conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
- }
- }
- else {
- /* otherwise we just copy, because an explicit opts setting
- * overrides all earlier +/- modifiers
- */
- conf->opts = new->opts;
- conf->opts_add = new->opts_add;
- conf->opts_remove = new->opts_remove;
- }
-
- if (!(new->override & OR_UNSET)) {
- conf->override = new->override;
- }
- if (new->ap_default_type) {
- conf->ap_default_type = new->ap_default_type;
- }
-
- if (new->ap_auth_type) {
- conf->ap_auth_type = new->ap_auth_type;
- }
- if (new->ap_auth_name) {
- conf->ap_auth_name = new->ap_auth_name;
- }
- if (new->ap_requires) {
- conf->ap_requires = new->ap_requires;
- }
-
- if (new->response_code_strings) {
- if (conf->response_code_strings == NULL) {
- conf->response_code_strings = apr_palloc(a,
- sizeof(*conf->response_code_strings) * RESPONSE_CODES);
- memcpy(conf->response_code_strings, new->response_code_strings,
- sizeof(*conf->response_code_strings) * RESPONSE_CODES);
- }
- else {
- for (i = 0; i < RESPONSE_CODES; ++i) {
- if (new->response_code_strings[i] != NULL) {
- conf->response_code_strings[i]
- = new->response_code_strings[i];
- }
- }
- }
- }
- if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
- conf->hostname_lookups = new->hostname_lookups;
- }
- if ((new->do_rfc1413 & 2) == 0) {
- conf->do_rfc1413 = new->do_rfc1413;
- }
- if ((new->content_md5 & 2) == 0) {
- conf->content_md5 = new->content_md5;
- }
- if (new->use_canonical_name != USE_CANONICAL_NAME_UNSET) {
- conf->use_canonical_name = new->use_canonical_name;
- }
-
-#ifdef RLIMIT_CPU
- if (new->limit_cpu) {
- conf->limit_cpu = new->limit_cpu;
- }
-#endif
-#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
- if (new->limit_mem) {
- conf->limit_mem = new->limit_mem;
- }
-#endif
-#ifdef RLIMIT_NPROC
- if (new->limit_nproc) {
- conf->limit_nproc = new->limit_nproc;
- }
-#endif
-
- if (new->limit_req_body) {
- conf->limit_req_body = new->limit_req_body;
- }
-
- if (new->limit_xml_body != AP_LIMIT_UNSET)
- conf->limit_xml_body = new->limit_xml_body;
- else
- conf->limit_xml_body = base->limit_xml_body;
-
- conf->sec = apr_array_append(a, base->sec, new->sec);
-
- if (new->satisfy != SATISFY_NOSPEC) {
- conf->satisfy = new->satisfy;
- }
-
-#ifdef WIN32
- if (new->script_interpreter_source != INTERPRETER_SOURCE_UNSET) {
- conf->script_interpreter_source = new->script_interpreter_source;
- }
-#endif
-
- if (new->server_signature != srv_sig_unset) {
- conf->server_signature = new->server_signature;
- }
-
- if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
- conf->add_default_charset = new->add_default_charset;
- if (new->add_default_charset_name) {
- conf->add_default_charset_name = new->add_default_charset_name;
- }
- }
- conf->output_filters = apr_array_append(a, base->output_filters,
- new->output_filters);
- conf->input_filters = apr_array_append(a, base->input_filters,
- new->input_filters);
-
- return (void*)conf;
-}
-
-static void *create_core_server_config(apr_pool_t *a, server_rec *s)
-{
- core_server_config *conf;
- int is_virtual = s->is_virtual;
-
- conf = (core_server_config *)apr_pcalloc(a, sizeof(core_server_config));
-#ifdef GPROF
- conf->gprof_dir = NULL;
-#endif
- conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
- conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
- conf->sec = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
- conf->sec_url = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
-
- return (void *)conf;
-}
-
-static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
-{
- core_server_config *base = (core_server_config *)basev;
- core_server_config *virt = (core_server_config *)virtv;
- core_server_config *conf;
-
- conf = (core_server_config *)apr_pcalloc(p, sizeof(core_server_config));
- *conf = *virt;
- if (!conf->access_name) {
- conf->access_name = base->access_name;
- }
- if (!conf->ap_document_root) {
- conf->ap_document_root = base->ap_document_root;
- }
- conf->sec = apr_array_append(p, base->sec, virt->sec);
- conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url);
-
- return conf;
-}
-
-/* Add per-directory configuration entry (for <directory> section);
- * these are part of the core server config.
- */
-
-AP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config)
-{
- core_server_config *sconf = ap_get_module_config(s->module_config,
- &core_module);
- void **new_space = (void **)apr_array_push(sconf->sec);
-
- *new_space = dir_config;
-}
-
-AP_CORE_DECLARE(void) ap_add_per_url_conf(server_rec *s, void *url_config)
-{
- core_server_config *sconf = ap_get_module_config(s->module_config,
- &core_module);
- void **new_space = (void **)apr_array_push(sconf->sec_url);
-
- *new_space = url_config;
-}
-
-AP_CORE_DECLARE(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
-{
- void **new_space = (void **)apr_array_push(conf->sec);
-
- *new_space = url_config;
-}
-
-/* core_reorder_directories reorders the directory sections such that the
- * 1-component sections come first, then the 2-component, and so on, finally
- * followed by the "special" sections. A section is "special" if it's a regex,
- * or if it doesn't start with / -- consider proxy: matching. All movements
- * are in-order to preserve the ordering of the sections from the config files.
- * See directory_walk().
- */
-
-#if defined(HAVE_DRIVE_LETTERS)
-#define IS_SPECIAL(entry_core) \
- ((entry_core)->r != NULL \
- || ((entry_core)->d[0] != '/' && (entry_core)->d[1] != ':'))
-#elif defined(NETWARE)
-/* XXX: Fairly certain this is correct... '/' must prefix the path
- * or else in the case xyz:/ or abc/xyz:/, '/' must follow the ':'.
- * If there is no leading '/' or embedded ':/', then we are special.
- */
-#define IS_SPECIAL(entry_core) \
- ((entry_core)->r != NULL \
- || ((entry_core)->d[0] != '/' \
- && strchr((entry_core)->d, ':') \
- && *(strchr((entry_core)->d, ':') + 1) != '/'))
-#else
-#define IS_SPECIAL(entry_core) \
- ((entry_core)->r != NULL || (entry_core)->d[0] != '/')
-#endif
-
-/* We need to do a stable sort, qsort isn't stable. So to make it stable
- * we'll be maintaining the original index into the list, and using it
- * as the minor key during sorting. The major key is the number of
- * components (where a "special" section has infinite components).
- */
-struct reorder_sort_rec {
- ap_conf_vector_t *elt;
- int orig_index;
-};
-
-static int reorder_sorter(const void *va, const void *vb)
-{
- const struct reorder_sort_rec *a = va;
- const struct reorder_sort_rec *b = vb;
- core_dir_config *core_a;
- core_dir_config *core_b;
-
- core_a = ap_get_module_config(a->elt, &core_module);
- core_b = ap_get_module_config(b->elt, &core_module);
- if (IS_SPECIAL(core_a)) {
- if (!IS_SPECIAL(core_b)) {
- return 1;
- }
- }
- else if (IS_SPECIAL(core_b)) {
- return -1;
- }
- else {
- /* we know they're both not special */
- if (core_a->d_components < core_b->d_components) {
- return -1;
- }
- else if (core_a->d_components > core_b->d_components) {
- return 1;
- }
- }
- /* Either they're both special, or they're both not special and have the
- * same number of components. In any event, we now have to compare
- * the minor key. */
- return a->orig_index - b->orig_index;
-}
-
-void ap_core_reorder_directories(apr_pool_t *p, server_rec *s)
-{
- core_server_config *sconf;
- apr_array_header_t *sec;
- struct reorder_sort_rec *sortbin;
- int nelts;
- ap_conf_vector_t **elts;
- int i;
- apr_pool_t *tmp;
-
- sconf = ap_get_module_config(s->module_config, &core_module);
- sec = sconf->sec;
- nelts = sec->nelts;
- elts = (ap_conf_vector_t **)sec->elts;
-
- /* we have to allocate tmp space to do a stable sort */
- apr_pool_create(&tmp, p);
- sortbin = apr_palloc(tmp, sec->nelts * sizeof(*sortbin));
- for (i = 0; i < nelts; ++i) {
- sortbin[i].orig_index = i;
- sortbin[i].elt = elts[i];
- }
-
- qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter);
-
- /* and now copy back to the original array */
- for (i = 0; i < nelts; ++i) {
- elts[i] = sortbin[i].elt;
- }
-
- apr_pool_destroy(tmp);
-}
-
-/*****************************************************************
- *
- * There are some elements of the core config structures in which
- * other modules have a legitimate interest (this is ugly, but necessary
- * to preserve NCSA back-compatibility). So, we have a bunch of accessors
- * here...
- */
-
-AP_DECLARE(int) ap_allow_options(request_rec *r)
-{
- core_dir_config *conf =
- (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
-
- return conf->opts;
-}
-
-AP_DECLARE(int) ap_allow_overrides(request_rec *r)
-{
- core_dir_config *conf;
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- return conf->override;
-}
-
-AP_DECLARE(const char *) ap_auth_type(request_rec *r)
-{
- core_dir_config *conf;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- return conf->ap_auth_type;
-}
-
-AP_DECLARE(const char *) ap_auth_name(request_rec *r)
-{
- core_dir_config *conf;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- return conf->ap_auth_name;
-}
-
-AP_DECLARE(const char *) ap_default_type(request_rec *r)
-{
- core_dir_config *conf;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- return conf->ap_default_type
- ? conf->ap_default_type
- : DEFAULT_CONTENT_TYPE;
-}
-
-AP_DECLARE(const char *) ap_document_root(request_rec *r) /* Don't use this! */
-{
- core_server_config *conf;
-
- conf = (core_server_config *)ap_get_module_config(r->server->module_config,
- &core_module);
- return conf->ap_document_root;
-}
-
-AP_DECLARE(const apr_array_header_t *) ap_requires(request_rec *r)
-{
- core_dir_config *conf;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- return conf->ap_requires;
-}
-
-AP_DECLARE(int) ap_satisfies(request_rec *r)
-{
- core_dir_config *conf;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- return conf->satisfy;
-}
-
-/* Should probably just get rid of this... the only code that cares is
- * part of the core anyway (and in fact, it isn't publicised to other
- * modules).
- */
-
-char *ap_response_code_string(request_rec *r, int error_index)
-{
- core_dir_config *conf;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- if (conf->response_code_strings == NULL) {
- return NULL;
- }
- return conf->response_code_strings[error_index];
-}
-
-
-/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
-static APR_INLINE void do_double_reverse (conn_rec *conn)
-{
- apr_sockaddr_t *sa;
- apr_status_t rv;
-
- if (conn->double_reverse) {
- /* already done */
- return;
- }
- if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
- /* single reverse failed, so don't bother */
- conn->double_reverse = -1;
- return;
- }
- rv = apr_sockaddr_info_get(&sa, conn->remote_host, APR_UNSPEC, 0, 0, conn->pool);
- if (rv == APR_SUCCESS) {
- while (sa) {
- if (sa->ipaddr_len == conn->remote_addr->ipaddr_len &&
- !memcmp(sa->ipaddr_ptr, conn->remote_addr->ipaddr_ptr,
- sa->ipaddr_len)) {
- conn->double_reverse = 1;
- return;
- }
-#if APR_HAVE_IPV6
- /* match IPv4-mapped IPv6 addresses with IPv4 A record */
- if (conn->remote_addr->sa.sin.sin_family == APR_INET6 &&
- sa->sa.sin.sin_family == APR_INET &&
- IN6_IS_ADDR_V4MAPPED((struct in6_addr *)conn->remote_addr->ipaddr_ptr) &&
- !memcmp(&((struct in6_addr *)conn->remote_addr->ipaddr_ptr)->s6_addr[12],
- sa->ipaddr_ptr,
- sizeof (((struct in_addr *)0)->s_addr))) {
- conn->double_reverse = 1;
- return;
- }
-#endif
- sa = sa->next;
- }
- }
- conn->double_reverse = -1;
-}
-
-AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
- int type, int *str_is_ip)
-{
- int hostname_lookups;
-
- if (str_is_ip) { /* if caller wants to know */
- *str_is_ip = 0;
- }
-
- /* If we haven't checked the host name, and we want to */
- if (dir_config) {
- hostname_lookups =
- ((core_dir_config *)ap_get_module_config(dir_config, &core_module))
- ->hostname_lookups;
- if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
- hostname_lookups = HOSTNAME_LOOKUP_OFF;
- }
- }
- else {
- /* the default */
- hostname_lookups = HOSTNAME_LOOKUP_OFF;
- }
-
- if (type != REMOTE_NOLOOKUP
- && conn->remote_host == NULL
- && (type == REMOTE_DOUBLE_REV
- || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
- apr_sockaddr_t *remote_addr;
-
- apr_socket_addr_get(&remote_addr, APR_REMOTE, conn->client_socket);
- if (apr_getnameinfo(&conn->remote_host, remote_addr, 0) == APR_SUCCESS) {
- ap_str_tolower(conn->remote_host);
-
- if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
- do_double_reverse(conn);
- if (conn->double_reverse != 1) {
- conn->remote_host = NULL;
- }
- }
- }
- /* if failed, set it to the NULL string to indicate error */
- if (conn->remote_host == NULL) {
- conn->remote_host = "";
- }
- }
- if (type == REMOTE_DOUBLE_REV) {
- do_double_reverse(conn);
- if (conn->double_reverse == -1) {
- return NULL;
- }
- }
-
-/*
- * Return the desired information; either the remote DNS name, if found,
- * or either NULL (if the hostname was requested) or the IP address
- * (if any identifier was requested).
- */
- if (conn->remote_host != NULL && conn->remote_host[0] != '\0') {
- return conn->remote_host;
- }
- else {
- if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) {
- return NULL;
- }
- else {
- if (str_is_ip) { /* if caller wants to know */
- *str_is_ip = 1;
- }
- return conn->remote_ip;
- }
- }
-}
-
-AP_DECLARE(const char *) ap_get_remote_logname(request_rec *r)
-{
- core_dir_config *dir_conf;
-
- if (r->connection->remote_logname != NULL) {
- return r->connection->remote_logname;
- }
-
-/* If we haven't checked the identity, and we want to */
- dir_conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- if (dir_conf->do_rfc1413 & 1) {
- return ap_rfc1413(r->connection, r->server);
- }
- else {
- return NULL;
- }
-}
-
-/* There are two options regarding what the "name" of a server is. The
- * "canonical" name as defined by ServerName and Port, or the "client's
- * name" as supplied by a possible Host: header or full URI. We never
- * trust the port passed in the client's headers, we always use the
- * port of the actual socket.
- *
- * The DNS option to UseCanonicalName causes this routine to do a
- * reverse lookup on the local IP address of the connection and use
- * that for the ServerName. This makes its value more reliable while
- * at the same time allowing Demon's magic virtual hosting to work.
- * The assumption is that DNS lookups are sufficiently quick...
- * -- fanf 1998-10-03
- */
-AP_DECLARE(const char *) ap_get_server_name(request_rec *r)
-{
- conn_rec *conn = r->connection;
- core_dir_config *d;
-
- d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- if (d->use_canonical_name == USE_CANONICAL_NAME_OFF) {
- return r->hostname ? r->hostname : r->server->server_hostname;
- }
- if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
- if (conn->local_host == NULL) {
- apr_sockaddr_t *local_addr;
-
- apr_socket_addr_get(&local_addr, APR_LOCAL, conn->client_socket);
- if (apr_getnameinfo(&conn->local_host, local_addr, 0) != APR_SUCCESS)
- conn->local_host = apr_pstrdup(conn->pool, r->server->server_hostname);
- else {
- ap_str_tolower(conn->local_host);
- }
- }
- return conn->local_host;
- }
- /* default */
- return r->server->server_hostname;
-}
-
-AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)
-{
- apr_port_t port;
- core_dir_config *d =
- (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
-
- port = r->server->port ? r->server->port : ap_default_port(r);
-
- if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
- || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
- if (r->hostname) {
- apr_sockaddr_t *localsa;
-
- apr_socket_addr_get(&localsa, APR_LOCAL, r->connection->client_socket);
- apr_sockaddr_port_get(&port, localsa);
- }
- }
- /* default */
- return port;
-}
-
-AP_DECLARE(char *) ap_construct_url(apr_pool_t *p, const char *uri,
- request_rec *r)
-{
- unsigned port = ap_get_server_port(r);
- const char *host = ap_get_server_name(r);
-
- if (ap_is_default_port(port, r)) {
- return apr_pstrcat(p, ap_http_method(r), "://", host, uri, NULL);
- }
- return apr_psprintf(p, "%s://%s:%u%s", ap_http_method(r), host, port, uri);
-}
-
-AP_DECLARE(unsigned long) ap_get_limit_req_body(const request_rec *r)
-{
- core_dir_config *d =
- (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
-
- return d->limit_req_body;
-}
-
-#ifdef WIN32
-static apr_status_t get_win32_registry_default_value(apr_pool_t *p, HKEY hkey,
- char* relativepath,
- char **value)
-{
- HKEY hkeyOpen;
- DWORD type;
- DWORD size = 0;
- DWORD result = RegOpenKeyEx(hkey, relativepath, 0,
- KEY_QUERY_VALUE, &hkeyOpen);
-
- if (result != ERROR_SUCCESS)
- return APR_FROM_OS_ERROR(result);
-
- /* Read to NULL buffer to determine value size */
- result = RegQueryValueEx(hkeyOpen, "", 0, &type, NULL, &size);
-
- if (result == ERROR_SUCCESS) {
- if ((size < 2) || (type != REG_SZ && type != REG_EXPAND_SZ)) {
- result = ERROR_INVALID_PARAMETER;
- }
- else {
- *value = apr_palloc(p, size);
- /* Read value based on size query above */
- result = RegQueryValueEx(hkeyOpen, "", 0, &type, *value, &size);
- }
- }
-
- /* TODO: This might look fine, but we need to provide some warning
- * somewhere that some environment variables may -not- be translated,
- * seeing as we may have chopped the environment table down somewhat.
- */
- if ((result == ERROR_SUCCESS) && (type == REG_EXPAND_SZ))
- {
- char *tmp = *value;
- size = ExpandEnvironmentStrings(tmp, *value, 0);
- if (size) {
- *value = apr_palloc(p, size);
- size = ExpandEnvironmentStrings(tmp, *value, size);
- }
- }
-
- RegCloseKey(hkeyOpen);
- return APR_FROM_OS_ERROR(result);
-}
-
-static char* get_interpreter_from_win32_registry(apr_pool_t *p, const char* ext,
- char** arguments, int strict)
-{
- char execcgi_path[] = "SHELL\\EXECCGI\\COMMAND";
- char execopen_path[] = "SHELL\\OPEN\\COMMAND";
- char typeName[MAX_PATH];
- int cmdOfName = FALSE;
- HKEY hkeyName;
- HKEY hkeyType;
- DWORD type;
- int size;
- int result;
- char *buffer;
- char *s;
-
- if (!ext)
- return NULL;
- /*
- * Future optimization:
- * When the registry is successfully searched, store the strings for
- * interpreter and arguments in an ext hash to speed up subsequent look-ups
- */
-
- /* Open the key associated with the script filetype extension */
- result = RegOpenKeyEx(HKEY_CLASSES_ROOT, ext, 0, KEY_QUERY_VALUE,
- &hkeyType);
-
- if (result != ERROR_SUCCESS)
- return NULL;
-
- /* Retrieve the name of the script filetype extension */
- size = sizeof(typeName);
- result = RegQueryValueEx(hkeyType, "", NULL, &type, typeName, &size);
-
- if (result == ERROR_SUCCESS && type == REG_SZ && typeName[0]) {
- /* Open the key associated with the script filetype extension */
- result = RegOpenKeyEx(HKEY_CLASSES_ROOT, typeName, 0,
- KEY_QUERY_VALUE, &hkeyName);
-
- if (result == ERROR_SUCCESS)
- cmdOfName = TRUE;
- }
-
- /* Open the key for the script command path by:
- *
- * 1) the 'named' filetype key for ExecCGI/Command
- * 2) the extension's type key for ExecCGI/Command
- *
- * and if the strict arg is false, then continue trying:
- *
- * 3) the 'named' filetype key for Open/Command
- * 4) the extension's type key for Open/Command
- */
-
- if (cmdOfName) {
- result = get_win32_registry_default_value(p, hkeyName,
- execcgi_path, &buffer);
- }
-
- if (!cmdOfName || (result != ERROR_SUCCESS)) {
- result = get_win32_registry_default_value(p, hkeyType,
- execcgi_path, &buffer);
- }
-
- if (!strict && cmdOfName && (result != ERROR_SUCCESS)) {
- result = get_win32_registry_default_value(p, hkeyName,
- execopen_path, &buffer);
- }
-
- if (!strict && (result != ERROR_SUCCESS)) {
- result = get_win32_registry_default_value(p, hkeyType,
- execopen_path, &buffer);
- }
-
- if (cmdOfName)
- RegCloseKey(hkeyName);
-
- RegCloseKey(hkeyType);
-
- if (result != ERROR_SUCCESS)
- return NULL;
-
- /*
- * The canonical way shell command entries are entered in the Win32
- * registry is as follows:
- * shell [options] "%1" [args]
- * where
- * shell - full path name to interpreter or shell to run.
- * E.g., c:\usr\local\ntreskit\perl\bin\perl.exe
- * options - optional switches
- * E.g., \C
- * "%1" - Place holder for file to run the shell against.
- * Typically quoted.
- * options - additional arguments
- * E.g., /silent
- *
- * If we find a %1 or a quoted %1, lop off the remainder to arguments.
- */
- if (buffer && *buffer) {
- if ((s = strstr(buffer, "\"%1")))
- {
- *s = '\0';
- *arguments = s + 4;
- }
- else if ((s = strstr(buffer, "%1")))
- {
- *s = '\0';
- *arguments = buffer + 2;
- }
- else
- *arguments = strchr(buffer, '\0');
- while (**arguments && isspace(**arguments))
- ++*arguments;
- }
-
- return buffer;
-}
-
-AP_DECLARE (file_type_e) ap_get_win32_interpreter(const request_rec *r,
- char** interpreter,
- char** arguments)
-{
- HANDLE hFile;
- DWORD nBytesRead;
- BOOLEAN bResult;
- char buffer[1024];
- core_dir_config *d;
- int i;
- file_type_e fileType = eFileTypeUNKNOWN;
- char *ext = NULL;
- char *exename = NULL;
-
- d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- /* Find the file extension */
- exename = strrchr(r->filename, '/');
- if (!exename) {
- exename = strrchr(r->filename, '\\');
- }
- if (!exename) {
- exename = r->filename;
- }
- else {
- exename++;
- }
- ext = strrchr(exename, '.');
-
- if (ext && (!strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd")))
- {
- char *comspec = getenv("COMSPEC");
- if (comspec) {
- *interpreter = apr_pstrcat(r->pool, "\"", comspec, "\" /c ", NULL);
- return eFileTypeSCRIPT;
- }
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r->server,
- "Failed to start a '%s' file as a script." APR_EOL_STR
- "\tCOMSPEC variable is missing from the environment.", ext);
- return eFileTypeUNKNOWN;
- }
-
- /* If the file has an extension and it is not .com and not .exe and
- * we've been instructed to search the registry, then do it!
- */
- if (ext && strcasecmp(ext,".exe") && strcasecmp(ext,".com") &&
- (d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY ||
- d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY_STRICT)) {
- /* Check the registry */
- int strict = (d->script_interpreter_source
- == INTERPRETER_SOURCE_REGISTRY_STRICT);
- *interpreter = get_interpreter_from_win32_registry(r->pool, ext,
- arguments, strict);
- if (*interpreter)
- return eFileTypeSCRIPT;
- else if (d->script_interpreter_source == INTERPRETER_SOURCE_REGISTRY_STRICT) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r->server,
- "ScriptInterpreterSource config directive set to \"registry-strict\"." APR_EOL_STR
- "\tInterpreter not found for files of type '%s'.", ext);
- return eFileTypeUNKNOWN;
- }
- else
- {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r->server,
- "ScriptInterpreterSource config directive set to \"registry\"." APR_EOL_STR
- "\tInterpreter not found for files of type '%s', "
- "trying \"script\" method...", ext);
- }
- }
-
- /* Need to peek into the file figure out what it really is... */
- /* This is wrong for Unicode FS ... should move to APR */
- hFile = CreateFile(r->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) {
- return eFileTypeUNKNOWN;
- }
- bResult = ReadFile(hFile, (void*) &buffer, sizeof(buffer) - 1,
- &nBytesRead, NULL);
- if (!bResult || (nBytesRead == 0)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, GetLastError(), r,
- "ReadFile(%s) failed", r->filename);
- CloseHandle(hFile);
- return eFileTypeUNKNOWN;
- }
- CloseHandle(hFile);
- buffer[nBytesRead] = '\0';
-
- /* Script or executable, that is the question... */
- if ((buffer[0] == '#') && (buffer[1] == '!')) {
- /* Assuming file is a script since it starts with a shebang */
- fileType = eFileTypeSCRIPT;
- for (i = 2; i < sizeof(buffer); i++) {
- if ((buffer[i] == '\r')
- || (buffer[i] == '\n')) {
- break;
- }
- }
- buffer[i] = '\0';
- for (i = 2; buffer[i] == ' ' ; ++i)
- ;
- *interpreter = apr_pstrdup(r->pool, buffer + i );
- }
- else {
- /* Not a script, is it an executable? */
- IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)buffer;
- if ((nBytesRead >= sizeof(IMAGE_DOS_HEADER)) && (hdr->e_magic == IMAGE_DOS_SIGNATURE)) {
- if (hdr->e_lfarlc < 0x40)
- fileType = eFileTypeEXE16;
- else
- fileType = eFileTypeEXE32;
- }
- else
- fileType = eFileTypeUNKNOWN;
- }
-
- return fileType;
-}
-#endif
-
-/*****************************************************************
- *
- * Commands... this module handles almost all of the NCSA httpd.conf
- * commands, but most of the old srm.conf is in the the modules.
- */
-
-
-/* returns a parent if it matches the given directive */
-static const ap_directive_t * find_parent(const ap_directive_t *dirp,
- const char *what)
-{
- while (dirp->parent != NULL) {
- dirp = dirp->parent;
- /* ### it would be nice to have atom-ized directives */
- if (strcasecmp(dirp->directive, what) == 0)
- return dirp;
- }
- return NULL;
-}
-
-AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd,
- unsigned forbidden)
-{
- const char *gt = (cmd->cmd->name[0] == '<'
- && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>')
- ? ">" : "";
- const ap_directive_t *found;
-
- if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual) {
- return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
- " cannot occur within <VirtualHost> section", NULL);
- }
-
- if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) {
- return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
- " cannot occur within <Limit> section", NULL);
- }
-
- if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE
- && cmd->path != NULL) {
- return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
- " cannot occur within <Directory/Location/Files> "
- "section", NULL);
- }
-
- if (((forbidden & NOT_IN_DIRECTORY)
- && ((found = find_parent(cmd->directive, "<Directory"))
- || (found = find_parent(cmd->directive, "<DirectoryMatch"))))
- || ((forbidden & NOT_IN_LOCATION)
- && ((found = find_parent(cmd->directive, "<Location"))
- || (found = find_parent(cmd->directive, "<LocationMatch"))))
- || ((forbidden & NOT_IN_FILES)
- && ((found = find_parent(cmd->directive, "<Files"))
- || (found = find_parent(cmd->directive, "<FilesMatch"))))) {
- return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
- " cannot occur within ", found->directive,
- "> section", NULL);
- }
-
- return NULL;
-}
-
-static const char *set_access_name(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- void *sconf = cmd->server->module_config;
- core_server_config *conf = ap_get_module_config(sconf, &core_module);
-
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- conf->access_name = apr_pstrdup(cmd->pool, arg);
- return NULL;
-}
-
-#ifdef GPROF
-static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, const char *arg)
-{
- void *sconf = cmd->server->module_config;
- core_server_config *conf = ap_get_module_config(sconf, &core_module);
-
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- conf->gprof_dir = apr_pstrdup(cmd->pool, arg);
- return NULL;
-}
-#endif /*GPROF*/
-
-static const char *set_add_default_charset(cmd_parms *cmd,
- void *d_, const char *arg)
-{
- core_dir_config *d=d_;
-
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
- if (!strcasecmp(arg, "Off")) {
- d->add_default_charset = ADD_DEFAULT_CHARSET_OFF;
- }
- else if (!strcasecmp(arg, "On")) {
- d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
- d->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
- }
- else {
- d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
- d->add_default_charset_name = arg;
- }
- return NULL;
-}
-
-static const char *set_document_root(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- void *sconf = cmd->server->module_config;
- core_server_config *conf = ap_get_module_config(sconf, &core_module);
-
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- arg = ap_os_canonical_filename(cmd->pool, arg);
- if (/* TODO: ap_configtestonly && ap_docrootcheck && */ !ap_is_directory(cmd->pool, arg)) {
- if (cmd->server->is_virtual) {
- ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, cmd->pool,
- "Warning: DocumentRoot [%s] does not exist",
- arg);
- }
- else {
- return "DocumentRoot must be a directory";
- }
- }
-
- conf->ap_document_root = arg;
- return NULL;
-}
-
-AP_DECLARE(void) ap_custom_response(request_rec *r, int status, char *string)
-{
- core_dir_config *conf =
- ap_get_module_config(r->per_dir_config, &core_module);
- int idx;
-
- if(conf->response_code_strings == NULL) {
- conf->response_code_strings =
- apr_pcalloc(r->pool,
- sizeof(*conf->response_code_strings) *
- RESPONSE_CODES);
- }
-
- idx = ap_index_of_response(status);
-
- conf->response_code_strings[idx] =
- ((ap_is_url(string) || (*string == '/')) && (*string != '"')) ?
- apr_pstrdup(r->pool, string) : apr_pstrcat(r->pool, "\"", string, NULL);
-}
-
-static const char *set_error_document(cmd_parms *cmd, void *conf_,
- const char *errno_str, const char *msg)
-{
- core_dir_config *conf=conf_;
- int error_number, index_number, idx500;
- enum { MSG, LOCAL_PATH, REMOTE_PATH } what = MSG;
-
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- /* 1st parameter should be a 3 digit number, which we recognize;
- * convert it into an array index
- */
- error_number = atoi(errno_str);
- idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
-
- if (error_number == HTTP_INTERNAL_SERVER_ERROR) {
- index_number = idx500;
- }
- else if ((index_number = ap_index_of_response(error_number)) == idx500) {
- return apr_pstrcat(cmd->pool, "Unsupported HTTP response code ",
- errno_str, NULL);
- }
-
- /* Heuristic to determine second argument. */
- if (ap_strchr_c(msg,' '))
- what = MSG;
- else if (msg[0] == '/')
- what = LOCAL_PATH;
- else if (ap_is_url(msg))
- what = REMOTE_PATH;
- else
- what = MSG;
-
- /* The entry should be ignored if it is a full URL for a 401 error */
-
- if (error_number == 401 && what == REMOTE_PATH) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, cmd->server,
- "cannot use a full URL in a 401 ErrorDocument "
- "directive --- ignoring!");
- }
- else { /* Store it... */
- if (conf->response_code_strings == NULL) {
- conf->response_code_strings =
- apr_pcalloc(cmd->pool,
- sizeof(*conf->response_code_strings) * RESPONSE_CODES);
- }
- /* hack. Prefix a " if it is a msg; as that is what
- * http_protocol.c relies on to distinguish between
- * a msg and a (local) path.
- */
- conf->response_code_strings[index_number] = (what == MSG) ?
- apr_pstrcat(cmd->pool, "\"",msg,NULL) :
- apr_pstrdup(cmd->pool, msg);
- }
-
- return NULL;
-}
-
-static const char *set_override(cmd_parms *cmd, void *d_, const char *l)
-{
- core_dir_config *d=d_;
- char *w;
-
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- d->override = OR_NONE;
- while (l[0]) {
- w = ap_getword_conf(cmd->pool, &l);
- if (!strcasecmp(w, "Limit")) {
- d->override |= OR_LIMIT;
- }
- else if (!strcasecmp(w, "Options")) {
- d->override |= OR_OPTIONS;
- }
- else if (!strcasecmp(w, "FileInfo")) {
- d->override |= OR_FILEINFO;
- }
- else if (!strcasecmp(w, "AuthConfig")) {
- d->override |= OR_AUTHCFG;
- }
- else if (!strcasecmp(w, "Indexes")) {
- d->override |= OR_INDEXES;
- }
- else if (!strcasecmp(w, "None")) {
- d->override = OR_NONE;
- }
- else if (!strcasecmp(w, "All")) {
- d->override = OR_ALL;
- }
- else {
- return apr_pstrcat(cmd->pool, "Illegal override option ", w, NULL);
- }
- d->override &= ~OR_UNSET;
- }
-
- return NULL;
-}
-
-static const char *set_options(cmd_parms *cmd, void *d_, const char *l)
-{
- core_dir_config *d=d_;
- allow_options_t opt;
- int first = 1;
- char action;
-
- while (l[0]) {
- char *w = ap_getword_conf(cmd->pool, &l);
- action = '\0';
-
- if (*w == '+' || *w == '-') {
- action = *(w++);
- }
- else if (first) {
- d->opts = OPT_NONE;
- first = 0;
- }
-
- if (!strcasecmp(w, "Indexes")) {
- opt = OPT_INDEXES;
- }
- else if (!strcasecmp(w, "Includes")) {
- opt = OPT_INCLUDES;
- }
- else if (!strcasecmp(w, "IncludesNOEXEC")) {
- opt = (OPT_INCLUDES | OPT_INCNOEXEC);
- }
- else if (!strcasecmp(w, "FollowSymLinks")) {
- opt = OPT_SYM_LINKS;
- }
- else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
- opt = OPT_SYM_OWNER;
- }
- else if (!strcasecmp(w, "execCGI")) {
- opt = OPT_EXECCGI;
- }
- else if (!strcasecmp(w, "MultiViews")) {
- opt = OPT_MULTI;
- }
- else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
- opt = OPT_MULTI|OPT_EXECCGI;
- }
- else if (!strcasecmp(w, "None")) {
- opt = OPT_NONE;
- }
- else if (!strcasecmp(w, "All")) {
- opt = OPT_ALL;
- }
- else {
- return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
- }
-
- /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
- if (action == '-') {
- d->opts_remove |= opt;
- d->opts_add &= ~opt;
- d->opts &= ~opt;
- }
- else if (action == '+') {
- d->opts_add |= opt;
- d->opts_remove &= ~opt;
- d->opts |= opt;
- }
- else {
- d->opts |= opt;
- }
- }
-
- return NULL;
-}
-
-static const char *satisfy(cmd_parms *cmd, void *c_, const char *arg)
-{
- core_dir_config *c=c_;
-
- if (!strcasecmp(arg, "all")) {
- c->satisfy = SATISFY_ALL;
- }
- else if (!strcasecmp(arg, "any")) {
- c->satisfy = SATISFY_ANY;
- }
- else {
- return "Satisfy either 'any' or 'all'.";
- }
- return NULL;
-}
-
-static const char *require(cmd_parms *cmd, void *c_, const char *arg)
-{
- require_line *r;
- core_dir_config *c=c_;
-
- if (!c->ap_requires) {
- c->ap_requires = apr_array_make(cmd->pool, 2, sizeof(require_line));
- }
- r = (require_line *)apr_array_push(c->ap_requires);
- r->requirement = apr_pstrdup(cmd->pool, arg);
- r->method_mask = cmd->limited;
- return NULL;
-}
-
-AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy,
- const char *arg) {
- const char *limited_methods = ap_getword(cmd->pool, &arg, '>');
- void *tog = cmd->cmd->cmd_data;
- int limited = 0;
- const char *errmsg;
-
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- while (limited_methods[0]) {
- char *method = ap_getword_conf(cmd->pool, &limited_methods);
- int methnum = ap_method_number_of(method);
-
- if (methnum == M_TRACE && !tog) {
- return "TRACE cannot be controlled by <Limit>";
- }
- else if (methnum == M_INVALID) {
- char **xmethod;
- register int i, j, k;
-
- /*
- * Deal with <Limit> by adding the method to the list.
- */
- if (!tog) {
- if (cmd->limited_xmethods == NULL) {
- cmd->limited_xmethods = apr_array_make(cmd->pool, 2,
- sizeof(char *));
- }
- xmethod = (char **) apr_array_push(cmd->limited_xmethods);
- *xmethod = apr_pstrdup(cmd->pool, method);
- }
- /*
- * <LimitExcept>, so remove any/all occurrences of the method
- * in the extension array.
- */
- else if ((cmd->limited_xmethods != NULL)
- && (cmd->limited_xmethods->nelts != 0)) {
- xmethod = (char **) cmd->limited_xmethods->elts;
- for (i = 0; i < cmd->limited_xmethods->nelts; ) {
- if (strcmp(xmethod[i], method) == 0) {
- for (j = i, k = i + 1;
- k < cmd->limited_xmethods->nelts;
- ++j, ++k) {
- xmethod[j] = xmethod[k];
- }
- cmd->limited_xmethods->nelts--;
- }
- }
- }
- }
- limited |= (1 << methnum);
- }
-
- /* Killing two features with one function,
- * if (tog == NULL) <Limit>, else <LimitExcept>
- */
- cmd->limited = tog ? ~limited : limited;
-
- errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
-
- cmd->limited = -1;
-
- return errmsg;
-}
-
-/* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that
- * people don't get bitten by wrong-cased regex matches
- */
-
-#ifdef WIN32
-#define USE_ICASE REG_ICASE
-#else
-#define USE_ICASE 0
-#endif
-
-/*
- * Report a missing-'>' syntax error.
- */
-static char *unclosed_directive(cmd_parms *cmd)
-{
- return apr_pstrcat(cmd->pool, cmd->cmd->name,
- "> directive missing closing '>'", NULL);
-}
-
-static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
-{
- const char *errmsg;
- const char *endp = ap_strrchr_c(arg, '>');
- int old_overrides = cmd->override;
- char *old_path = cmd->path;
- core_dir_config *conf;
- ap_conf_vector_t *new_dir_conf = ap_create_per_dir_config(cmd->pool);
- regex_t *r = NULL;
- const command_rec *thiscmd = cmd->cmd;
-
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- if (endp == NULL) {
- return unclosed_directive(cmd);
- }
-
- arg=apr_pstrndup(cmd->pool, arg, endp-arg);
-
- cmd->path = ap_getword_conf(cmd->pool, &arg);
- cmd->override = OR_ALL|ACCESS_CONF;
-
- if (thiscmd->cmd_data) { /* <DirectoryMatch> */
- r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
- }
- else if (!strcmp(cmd->path, "~")) {
- cmd->path = ap_getword_conf(cmd->pool, &arg);
- r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
- }
-#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
- else if (strcmp(cmd->path, "/") == 0) {
- /* Treat 'default' path / as an inalienable root */
- cmd->path = apr_pstrdup(cmd->pool, cmd->path);
- }
-#endif
-#if defined(HAVE_UNC_PATHS)
- else if (strcmp(cmd->path, "//") == 0) {
- /* Treat UNC path // as an inalienable root */
- cmd->path = apr_pstrdup(cmd->pool, cmd->path);
- }
-#endif
- else {
- /* Ensure that the pathname is canonical */
- cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
- }
-
- /* initialize our config and fetch it */
- conf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path,
- &core_module, cmd->pool);
-
- errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf);
- if (errmsg != NULL)
- return errmsg;
-
- conf->r = r;
-
- ap_add_per_dir_conf(cmd->server, new_dir_conf);
-
- if (*arg != '\0') {
- return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
- "> arguments not (yet) supported.", NULL);
- }
-
- cmd->path = old_path;
- cmd->override = old_overrides;
-
- return NULL;
-}
-
-static const char *urlsection(cmd_parms *cmd, void *mconfig, const char *arg)
-{
- const char *errmsg;
- const char *endp = ap_strrchr_c(arg, '>');
- int old_overrides = cmd->override;
- char *old_path = cmd->path;
- core_dir_config *conf;
- regex_t *r = NULL;
- const command_rec *thiscmd = cmd->cmd;
- ap_conf_vector_t *new_url_conf = ap_create_per_dir_config(cmd->pool);
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- if (endp == NULL) {
- return unclosed_directive(cmd);
- }
-
- arg=apr_pstrndup(cmd->pool, arg, endp-arg);
-
- cmd->path = ap_getword_conf(cmd->pool, &arg);
- cmd->override = OR_ALL|ACCESS_CONF;
-
- if (thiscmd->cmd_data) { /* <LocationMatch> */
- r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
- }
- else if (!strcmp(cmd->path, "~")) {
- cmd->path = ap_getword_conf(cmd->pool, &arg);
- r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
- }
-
- /* initialize our config and fetch it */
- conf = ap_set_config_vectors(cmd->server, new_url_conf, cmd->path,
- &core_module, cmd->pool);
-
- errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_url_conf);
- if (errmsg != NULL)
- return errmsg;
-
- conf->d = apr_pstrdup(cmd->pool, cmd->path); /* No mangling, please */
- conf->d_is_fnmatch = apr_is_fnmatch(conf->d) != 0;
- conf->r = r;
-
- ap_add_per_url_conf(cmd->server, new_url_conf);
-
- if (*arg != '\0') {
- return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
- "> arguments not (yet) supported.", NULL);
- }
-
- cmd->path = old_path;
- cmd->override = old_overrides;
-
- return NULL;
-}
-
-static const char *filesection(cmd_parms *cmd, void *mconfig, const char *arg)
-{
- const char *errmsg;
- const char *endp = ap_strrchr_c(arg, '>');
- int old_overrides = cmd->override;
- char *old_path = cmd->path;
- core_dir_config *conf;
- regex_t *r = NULL;
- const command_rec *thiscmd = cmd->cmd;
- core_dir_config *c=mconfig;
- ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool);
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_LOCATION);
-
- if (err != NULL) {
- return err;
- }
-
- if (endp == NULL) {
- return unclosed_directive(cmd);
- }
-
- arg=apr_pstrndup(cmd->pool, arg, endp-arg);
-
- cmd->path = ap_getword_conf(cmd->pool, &arg);
- /* Only if not an .htaccess file */
- if (!old_path) {
- cmd->override = OR_ALL|ACCESS_CONF;
- }
-
- if (thiscmd->cmd_data) { /* <FilesMatch> */
- r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
- }
- else if (!strcmp(cmd->path, "~")) {
- cmd->path = ap_getword_conf(cmd->pool, &arg);
- r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
- }
- else {
- /* Ensure that the pathname is canonical */
- cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
- }
-
- /* initialize our config and fetch it */
- conf = ap_set_config_vectors(cmd->server, new_file_conf, cmd->path,
- &core_module, cmd->pool);
-
- errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_file_conf);
- if (errmsg != NULL)
- return errmsg;
-
- conf->d = cmd->path;
- conf->d_is_fnmatch = apr_is_fnmatch(conf->d) != 0;
- conf->r = r;
-
- ap_add_file_conf(c, new_file_conf);
-
- if (*arg != '\0') {
- return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,
- "> arguments not (yet) supported.", NULL);
- }
-
- cmd->path = old_path;
- cmd->override = old_overrides;
-
- return NULL;
-}
-
-static const char *start_ifmod(cmd_parms *cmd, void *mconfig, const char *arg)
-{
- const char *endp = ap_strrchr_c(arg, '>');
- int not = (arg[0] == '!');
- module *found;
-
- if (endp == NULL) {
- return unclosed_directive(cmd);
- }
-
- arg=apr_pstrndup(cmd->pool, arg, endp-arg);
-
- if (not) {
- arg++;
- }
-
- found = ap_find_linked_module(arg);
-
- if ((!not && found) || (not && !found)) {
- ap_directive_t *parent = NULL;
- ap_directive_t *current = NULL;
- const char *retval;
-
- retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
- &current, &parent, "<IfModule");
- *(ap_directive_t **)mconfig = current;
- return retval;
- }
- else {
- *(ap_directive_t **)mconfig = NULL;
- return ap_soak_end_container(cmd, "<IfModule");
- }
-}
-
-AP_DECLARE(int) ap_exists_config_define(const char *name)
-{
- char **defines;
- int i;
-
- defines = (char **)ap_server_config_defines->elts;
- for (i = 0; i < ap_server_config_defines->nelts; i++) {
- if (strcmp(defines[i], name) == 0) {
- return 1;
- }
- }
- return 0;
-}
-
-static const char *start_ifdefine(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *endp;
- int defined;
- int not = 0;
-
- endp = ap_strrchr_c(arg, '>');
- if (endp == NULL) {
- return unclosed_directive(cmd);
- }
-
- arg=apr_pstrndup(cmd->pool, arg, endp-arg);
-
- if (arg[0] == '!') {
- not = 1;
- arg++;
- }
-
- defined = ap_exists_config_define(arg);
- if ((!not && defined) || (not && !defined)) {
- ap_directive_t *parent = NULL;
- ap_directive_t *current = NULL;
- const char *retval;
-
- retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
- &current, &parent, "<IfDefine");
- *(ap_directive_t **)dummy = current;
- return retval;
- }
- else {
- *(ap_directive_t **)dummy = NULL;
- return ap_soak_end_container(cmd, "<IfDefine");
- }
-}
-
-/* httpd.conf commands... beginning with the <VirtualHost> business */
-
-static const char *virtualhost_section(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- server_rec *main_server = cmd->server, *s;
- const char *errmsg;
- const char *endp = ap_strrchr_c(arg, '>');
- apr_pool_t *p = cmd->pool;
-
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (endp == NULL) {
- return unclosed_directive(cmd);
- }
-
- arg=apr_pstrndup(cmd->pool, arg, endp-arg);
-
- /* FIXME: There's another feature waiting to happen here -- since you
- can now put multiple addresses/names on a single <VirtualHost>
- you might want to use it to group common definitions and then
- define other "subhosts" with their individual differences. But
- personally I'd rather just do it with a macro preprocessor. -djg */
- if (main_server->is_virtual) {
- return "<VirtualHost> doesn't nest!";
- }
-
- errmsg = ap_init_virtual_host(p, arg, main_server, &s);
- if (errmsg) {
- return errmsg;
- }
-
- s->next = main_server->next;
- main_server->next = s;
-
- s->defn_name = cmd->directive->filename;
- s->defn_line_number = cmd->directive->line_num;
-
- cmd->server = s;
-
- errmsg = ap_walk_config(cmd->directive->first_child, cmd,
- s->lookup_defaults);
-
- cmd->server = main_server;
-
- return errmsg;
-}
-
-static const char *set_server_alias(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- if (!cmd->server->names) {
- return "ServerAlias only used in <VirtualHost>";
- }
- while (*arg) {
- char **item, *name = ap_getword_conf(cmd->pool, &arg);
- if (ap_is_matchexp(name)) {
- item = (char **)apr_array_push(cmd->server->wild_names);
- }
- else {
- item = (char **)apr_array_push(cmd->server->names);
- }
- *item = name;
- }
- return NULL;
-}
-
-static const char *add_filter(cmd_parms *cmd, void *dummy, const char *arg)
-{
- core_dir_config *conf = dummy;
- char **newfilter;
-
- newfilter = (char **)apr_array_push(conf->output_filters);
- *newfilter = apr_pstrdup(cmd->pool, arg);
- return NULL;
-}
-
-static const char *add_input_filter(cmd_parms *cmd, void *dummy, const char *arg)
-{
- core_dir_config *conf = dummy;
- char **newfilter;
-
- newfilter = (char **)apr_array_push(conf->input_filters);
- *newfilter = apr_pstrdup(cmd->pool, arg);
- return NULL;
-}
-
-static const char *set_server_string_slot(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- /* This one's pretty generic... */
-
- int offset = (int)(long)cmd->info;
- char *struct_ptr = (char *)cmd->server;
-
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- *(const char **)(struct_ptr + offset) = arg;
- return NULL;
-}
-
-static const char *server_port(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- int port;
-
- if (err != NULL) {
- return err;
- }
- port = atoi(arg);
- if (port <= 0 || port >= 65536) { /* 65536 == 1<<16 */
- return apr_pstrcat(cmd->temp_pool, "The port number \"", arg,
- "\" is outside the appropriate range "
- "(i.e., 1..65535).", NULL);
- }
- cmd->server->port = port;
- return NULL;
-}
-
-static const char *set_signature_flag(cmd_parms *cmd, void *d_,
- const char *arg)
-{
- core_dir_config *d=d_;
-
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- if (strcasecmp(arg, "On") == 0) {
- d->server_signature = srv_sig_on;
- }
- else if (strcasecmp(arg, "Off") == 0) {
- d->server_signature = srv_sig_off;
- }
- else if (strcasecmp(arg, "EMail") == 0) {
- d->server_signature = srv_sig_withmail;
- }
- else {
- return "ServerSignature: use one of: off | on | email";
- }
- return NULL;
-}
-
-static const char *set_server_root(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
-
- if (err != NULL) {
- return err;
- }
-
- arg = ap_os_canonical_filename(cmd->pool, arg);
-
- if (!ap_is_directory(cmd->pool, arg)) {
- return "ServerRoot must be a valid directory";
- }
- ap_server_root = arg;
- return NULL;
-}
-
-static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- cmd->server->timeout = atoi(arg);
- return NULL;
-}
-
-static const char *set_idcheck(cmd_parms *cmd, void *d_, int arg)
-{
- core_dir_config *d=d_;
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- d->do_rfc1413 = arg != 0;
- return NULL;
-}
-
-static const char *set_hostname_lookups(cmd_parms *cmd, void *d_,
- const char *arg)
-{
- core_dir_config *d=d_;
-
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- if (!strcasecmp(arg, "on")) {
- d->hostname_lookups = HOSTNAME_LOOKUP_ON;
- }
- else if (!strcasecmp(arg, "off")) {
- d->hostname_lookups = HOSTNAME_LOOKUP_OFF;
- }
- else if (!strcasecmp(arg, "double")) {
- d->hostname_lookups = HOSTNAME_LOOKUP_DOUBLE;
- }
- else {
- return "parameter must be 'on', 'off', or 'double'";
- }
- return NULL;
-}
-
-static const char *set_serverpath(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- cmd->server->path = arg;
- cmd->server->pathlen = strlen(arg);
- return NULL;
-}
-
-static const char *set_content_md5(cmd_parms *cmd, void *d_, int arg)
-{
- core_dir_config *d=d_;
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- d->content_md5 = arg != 0;
- return NULL;
-}
-
-static const char *set_use_canonical_name(cmd_parms *cmd, void *d_,
- const char *arg)
-{
- core_dir_config *d=d_;
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- if (strcasecmp(arg, "on") == 0) {
- d->use_canonical_name = USE_CANONICAL_NAME_ON;
- }
- else if (strcasecmp(arg, "off") == 0) {
- d->use_canonical_name = USE_CANONICAL_NAME_OFF;
- }
- else if (strcasecmp(arg, "dns") == 0) {
- d->use_canonical_name = USE_CANONICAL_NAME_DNS;
- }
- else {
- return "parameter must be 'on', 'off', or 'dns'";
- }
- return NULL;
-}
-
-
-static const char *include_config (cmd_parms *cmd, void *dummy,
- const char *name)
-{
- ap_directive_t *conftree = NULL;
-
- ap_process_resource_config(cmd->server,
- ap_server_root_relative(cmd->pool, name),
- &conftree, cmd->pool, cmd->temp_pool);
- *(ap_directive_t **)dummy = conftree;
- return NULL;
-}
-
-static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg)
-{
- char *str;
-
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- if ((str = ap_getword_conf(cmd->pool, &arg))) {
- if (!strcasecmp(str, "emerg")) {
- cmd->server->loglevel = APLOG_EMERG;
- }
- else if (!strcasecmp(str, "alert")) {
- cmd->server->loglevel = APLOG_ALERT;
- }
- else if (!strcasecmp(str, "crit")) {
- cmd->server->loglevel = APLOG_CRIT;
- }
- else if (!strcasecmp(str, "error")) {
- cmd->server->loglevel = APLOG_ERR;
- }
- else if (!strcasecmp(str, "warn")) {
- cmd->server->loglevel = APLOG_WARNING;
- }
- else if (!strcasecmp(str, "notice")) {
- cmd->server->loglevel = APLOG_NOTICE;
- }
- else if (!strcasecmp(str, "info")) {
- cmd->server->loglevel = APLOG_INFO;
- }
- else if (!strcasecmp(str, "debug")) {
- cmd->server->loglevel = APLOG_DEBUG;
- }
- else {
- return "LogLevel requires level keyword: one of "
- "emerg/alert/crit/error/warn/notice/info/debug";
- }
- }
- else {
- return "LogLevel requires level keyword";
- }
-
- return NULL;
-}
-
-AP_DECLARE(const char *) ap_psignature(const char *prefix, request_rec *r)
-{
- char sport[20];
- core_dir_config *conf;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- if ((conf->server_signature == srv_sig_off)
- || (conf->server_signature == srv_sig_unset)) {
- return "";
- }
-
- apr_snprintf(sport, sizeof sport, "%u", (unsigned) ap_get_server_port(r));
-
- if (conf->server_signature == srv_sig_withmail) {
- return apr_pstrcat(r->pool, prefix, "<ADDRESS>" AP_SERVER_BASEVERSION
- " Server at <A HREF=\"mailto:",
- r->server->server_admin, "\">",
- ap_get_server_name(r), "</A> Port ", sport,
- "</ADDRESS>\n", NULL);
- }
- return apr_pstrcat(r->pool, prefix, "<ADDRESS>" AP_SERVER_BASEVERSION
- " Server at ", ap_get_server_name(r), " Port ", sport,
- "</ADDRESS>\n", NULL);
-}
-
-/*
- * Load an authorisation realm into our location configuration, applying the
- * usual rules that apply to realms.
- */
-static const char *set_authname(cmd_parms *cmd, void *mconfig,
- const char *word1)
-{
- core_dir_config *aconfig = (core_dir_config *)mconfig;
-
- aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
- return NULL;
-}
-
-#ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
-static const char *set_bs2000_account(cmd_parms *cmd, void *dummy, char *name)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- return os_set_account(cmd->pool, name);
-}
-#endif /*_OSD_POSIX*/
-
-/*
- * Handle a request to include the server's OS platform in the Server
- * response header field (the ServerTokens directive). Unfortunately
- * this requires a new global in order to communicate the setting back to
- * http_main so it can insert the information in the right place in the
- * string.
- */
-
-static char *server_version = NULL;
-static int version_locked = 0;
-
-enum server_token_type {
- SrvTk_MIN, /* eg: Apache/1.3.0 */
- SrvTk_OS, /* eg: Apache/1.3.0 (UNIX) */
- SrvTk_FULL, /* eg: Apache/1.3.0 (UNIX) PHP/3.0 FooBar/1.2b */
- SrvTk_PRODUCT_ONLY /* eg: Apache */
-};
-static enum server_token_type ap_server_tokens = SrvTk_FULL;
-
-static apr_status_t reset_version(void *dummy)
-{
- version_locked = 0;
- ap_server_tokens = SrvTk_FULL;
- server_version = NULL;
- return APR_SUCCESS;
-}
-
-AP_DECLARE(const char *) ap_get_server_version(void)
-{
- return (server_version ? server_version : AP_SERVER_BASEVERSION);
-}
-
-AP_DECLARE(void) ap_add_version_component(apr_pool_t *pconf, const char *component)
-{
- if (! version_locked) {
- /*
- * If the version string is null, register our cleanup to reset the
- * pointer on pool destruction. We also know that, if NULL,
- * we are adding the original SERVER_BASEVERSION string.
- */
- if (server_version == NULL) {
- apr_pool_cleanup_register(pconf, NULL, reset_version,
- apr_pool_cleanup_null);
- server_version = apr_pstrdup(pconf, component);
- }
- else {
- /*
- * Tack the given component identifier to the end of
- * the existing string.
- */
- server_version = apr_pstrcat(pconf, server_version, " ",
- component, NULL);
- }
- }
-}
-
-/*
- * This routine adds the real server base identity to the version string,
- * and then locks out changes until the next reconfig.
- */
-static void ap_set_version(apr_pool_t *pconf)
-{
- if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
- ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
- }
- else if (ap_server_tokens == SrvTk_MIN) {
- ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
- }
- else {
- ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
- }
- /*
- * Lock the server_version string if we're not displaying
- * the full set of tokens
- */
- if (ap_server_tokens != SrvTk_FULL) {
- version_locked++;
- }
-}
-
-static const char *set_serv_tokens(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (!strcasecmp(arg, "OS")) {
- ap_server_tokens = SrvTk_OS;
- }
- else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
- ap_server_tokens = SrvTk_MIN;
- }
- else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
- ap_server_tokens = SrvTk_PRODUCT_ONLY;
- }
- else {
- ap_server_tokens = SrvTk_FULL;
- }
- return NULL;
-}
-
-static const char *set_limit_req_line(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- int lim;
-
- if (err != NULL) {
- return err;
- }
- lim = atoi(arg);
- if (lim < 0) {
- return apr_pstrcat(cmd->temp_pool, "LimitRequestLine \"", arg,
- "\" must be a non-negative integer", NULL);
- }
- if (lim > DEFAULT_LIMIT_REQUEST_LINE) {
- return apr_psprintf(cmd->temp_pool, "LimitRequestLine \"%s\" "
- "must not exceed the precompiled maximum of %d",
- arg, DEFAULT_LIMIT_REQUEST_LINE);
- }
- cmd->server->limit_req_line = lim;
- return NULL;
-}
-
-static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- int lim;
-
- if (err != NULL) {
- return err;
- }
- lim = atoi(arg);
- if (lim < 0) {
- return apr_pstrcat(cmd->temp_pool, "LimitRequestFieldsize \"", arg,
- "\" must be a non-negative integer (0 = no limit)",
- NULL);
- }
- if (lim > DEFAULT_LIMIT_REQUEST_FIELDSIZE) {
- return apr_psprintf(cmd->temp_pool, "LimitRequestFieldsize \"%s\" "
- "must not exceed the precompiled maximum of %d",
- arg, DEFAULT_LIMIT_REQUEST_FIELDSIZE);
- }
- cmd->server->limit_req_fieldsize = lim;
- return NULL;
-}
-
-static const char *set_limit_req_fields(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- int lim;
-
- if (err != NULL) {
- return err;
- }
- lim = atoi(arg);
- if (lim < 0) {
- return apr_pstrcat(cmd->temp_pool, "LimitRequestFields \"", arg,
- "\" must be a non-negative integer (0 = no limit)",
- NULL);
- }
- cmd->server->limit_req_fields = lim;
- return NULL;
-}
-
-static const char *set_limit_req_body(cmd_parms *cmd, void *conf_,
- const char *arg)
-{
- core_dir_config *conf=conf_;
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- /* WTF: If strtoul is not portable, then write a replacement.
- * Instead we have an idiotic define in httpd.h that prevents
- * it from being used even when it is available. Sheesh.
- */
- conf->limit_req_body = (unsigned long)strtol(arg, (char **)NULL, 10);
- return NULL;
-}
-
-static const char *set_limit_xml_req_body(cmd_parms *cmd, void *conf_,
- const char *arg)
-{
- core_dir_config *conf = conf_;
- const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- conf->limit_xml_body = atol(arg);
- if (conf->limit_xml_body < 0)
- return "LimitXMLRequestBody requires a non-negative integer.";
-
- return NULL;
-}
-
-AP_DECLARE(size_t) ap_get_limit_xml_body(const request_rec *r)
-{
- core_dir_config *conf;
-
- conf = ap_get_module_config(r->per_dir_config, &core_module);
- if (conf->limit_xml_body == AP_LIMIT_UNSET)
- return AP_DEFAULT_LIMIT_XML_BODY;
- return (size_t)conf->limit_xml_body;
-}
-
-#ifdef WIN32
-static const char *set_interpreter_source(cmd_parms *cmd, core_dir_config *d,
- char *arg)
-{
- if (!strcasecmp(arg, "registry")) {
- d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY;
- } else if (!strcasecmp(arg, "registry-strict")) {
- d->script_interpreter_source = INTERPRETER_SOURCE_REGISTRY_STRICT;
- } else if (!strcasecmp(arg, "script")) {
- d->script_interpreter_source = INTERPRETER_SOURCE_SHEBANG;
- } else {
- return apr_pstrcat(cmd->temp_pool, "ScriptInterpreterSource \"", arg,
- "\" must be \"registry\", \"registry-strict\" or "
- "\"script\"", NULL);
- }
- return NULL;
-}
-#endif
-
-#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
-static const char *no_set_limit(cmd_parms *cmd, void *conf_,
- const char *arg, const char *arg2)
-{
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, cmd->server,
- "%s not supported on this platform", cmd->cmd->name);
- return NULL;
-}
-#endif
-
-#ifdef RLIMIT_CPU
-static const char *set_limit_cpu(cmd_parms *cmd, void *conf_,
- const char *arg, const char *arg2)
-{
- core_dir_config *conf=conf_;
-
- unixd_set_rlimit(cmd, &conf->limit_cpu, arg, arg2, RLIMIT_CPU);
- return NULL;
-}
-#endif
-
-#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
-static const char *set_limit_mem(cmd_parms *cmd, void *conf_,
- const char *arg, const char * arg2)
-{
- core_dir_config *conf=conf_;
-
-#if defined(RLIMIT_AS)
- unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2 ,RLIMIT_AS);
-#elif defined(RLIMIT_DATA)
- unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_DATA);
-#elif defined(RLIMIT_VMEM)
- unixd_set_rlimit(cmd, &conf->limit_mem, arg, arg2, RLIMIT_VMEM);
-#endif
- return NULL;
-}
-#endif
-
-#ifdef RLIMIT_NPROC
-static const char *set_limit_nproc(cmd_parms *cmd, void *conf_,
- const char *arg, const char * arg2)
-{
- core_dir_config *conf=conf_;
-
- unixd_set_rlimit(cmd, &conf->limit_nproc, arg, arg2, RLIMIT_NPROC);
- return NULL;
-}
-#endif
-
-static apr_status_t writev_it_all(apr_socket_t *s,
- struct iovec *vec, int nvec,
- apr_size_t len, apr_size_t *nbytes)
-{
- apr_size_t bytes_written = 0;
- apr_status_t rv;
- apr_size_t n = len;
- apr_size_t i = 0;
-
- *nbytes = 0;
-
- /* XXX handle checking for non-blocking socket */
- while (bytes_written != len) {
- rv = apr_sendv(s, vec + i, nvec - i, &n);
- bytes_written += n;
- if (rv != APR_SUCCESS)
- return rv;
- *nbytes += n;
-
- /* If the write did not complete, adjust the iovecs and issue
- * apr_sendv again
- */
- if (bytes_written < len) {
- /* Skip over the vectors that have already been written */
- apr_size_t cnt = vec[i].iov_len;
- while (n >= cnt && i + 1 < nvec) {
- i++;
- cnt += vec[i].iov_len;
- }
- if (n < cnt) {
- /* Handle partial write of vec i */
- vec[i].iov_base = (char *) vec[i].iov_base +
- (vec[i].iov_len - (cnt - n));
- vec[i].iov_len = cnt -n;
- }
- }
- n = len - bytes_written;
- }
-
- return APR_SUCCESS;
-}
-
-/* sendfile_it_all()
- * send the entire file using sendfile()
- * handle partial writes
- * return only when all bytes have been sent or an error is encountered.
- */
-
-#if APR_HAS_SENDFILE
-static apr_status_t sendfile_it_all(conn_rec *c,
- apr_file_t *fd,
- apr_hdtr_t *hdtr,
- apr_off_t file_offset,
- apr_size_t file_bytes_left,
- apr_size_t total_bytes_left,
- apr_int32_t flags)
-{
- apr_status_t rv;
-#ifdef AP_DEBUG
- apr_int32_t timeout = 0;
-#endif
-
- AP_DEBUG_ASSERT((apr_getsocketopt(c->client_socket, APR_SO_TIMEOUT,
- &timeout) == APR_SUCCESS) &&
- timeout > 0); /* socket must be in timeout mode */
- do {
- apr_size_t tmplen = file_bytes_left;
-
- rv = apr_sendfile(c->client_socket, fd, hdtr, &file_offset, &tmplen,
- flags);
- total_bytes_left -= tmplen;
- if (!total_bytes_left || rv != APR_SUCCESS) {
- return rv; /* normal case & error exit */
- }
-
- AP_DEBUG_ASSERT(total_bytes_left > 0 && tmplen > 0);
-
- /* partial write, oooh noooo...
- * Skip over any header data which was written
- */
- while (tmplen && hdtr->numheaders) {
- if (tmplen >= hdtr->headers[0].iov_len) {
- tmplen -= hdtr->headers[0].iov_len;
- --hdtr->numheaders;
- ++hdtr->headers;
- }
- else {
- char *iov_base = (char *)hdtr->headers[0].iov_base;
-
- hdtr->headers[0].iov_len -= tmplen;
- iov_base += tmplen;
- hdtr->headers[0].iov_base = iov_base;
- tmplen = 0;
- }
- }
-
- /* Skip over any file data which was written */
-
- if (tmplen <= file_bytes_left) {
- file_offset += tmplen;
- file_bytes_left -= tmplen;
- continue;
- }
- tmplen -= file_bytes_left;
- file_bytes_left = 0;
- file_offset = 0;
-
- /* Skip over any trailer data which was written */
-
- while (tmplen && hdtr->numtrailers) {
- if (tmplen >= hdtr->trailers[0].iov_len) {
- tmplen -= hdtr->trailers[0].iov_len;
- --hdtr->numtrailers;
- ++hdtr->trailers;
- }
- else {
- char *iov_base = (char *)hdtr->trailers[0].iov_base;
-
- hdtr->trailers[0].iov_len -= tmplen;
- iov_base += tmplen;
- hdtr->trailers[0].iov_base = iov_base;
- tmplen = 0;
- }
- }
- } while (1);
-}
-#endif
-
-/*
- * send_the_file()
- * Sends the contents of file fd along with header/trailer bytes, if any,
- * to the network. send_the_file will return only when all the bytes have been
- * sent (i.e., it handles partial writes) or on a network error condition.
- */
-static apr_status_t send_the_file(conn_rec *c, apr_file_t *fd,
- apr_hdtr_t *hdtr, apr_off_t offset,
- apr_size_t length, apr_size_t *nbytes)
-{
- apr_status_t rv = APR_SUCCESS;
- apr_int32_t togo; /* Remaining number of bytes in the file to send */
- apr_size_t sendlen = 0;
- apr_size_t bytes_sent;
- apr_int32_t i;
- apr_off_t o; /* Track the file offset for partial writes */
- char buffer[8192];
-
- *nbytes = 0;
-
- /* Send the headers
- * writev_it_all handles partial writes.
- * XXX: optimization... if headers are less than MIN_WRITE_SIZE, copy
- * them into buffer
- */
- if ( hdtr && hdtr->numheaders > 0 ) {
- for (i = 0; i < hdtr->numheaders; i++) {
- sendlen += hdtr->headers[i].iov_len;
- }
- rv = writev_it_all(c->client_socket, hdtr->headers, hdtr->numheaders,
- sendlen, &bytes_sent);
- if (rv == APR_SUCCESS)
- *nbytes += bytes_sent; /* track total bytes sent */
- }
-
- /* Seek the file to 'offset' */
- if (offset != 0 && rv == APR_SUCCESS) {
- rv = apr_file_seek(fd, APR_SET, &offset);
- }
-
- /* Send the file, making sure to handle partial writes */
- togo = length;
- while (rv == APR_SUCCESS && togo) {
- sendlen = togo > sizeof(buffer) ? sizeof(buffer) : togo;
- o = 0;
- rv = apr_file_read(fd, buffer, &sendlen);
- while (rv == APR_SUCCESS && sendlen) {
- bytes_sent = sendlen;
- rv = apr_send(c->client_socket, &buffer[o], &bytes_sent);
- if (rv == APR_SUCCESS) {
- sendlen -= bytes_sent; /* sendlen != bytes_sent ==> partial write */
- o += bytes_sent; /* o is where we are in the buffer */
- *nbytes += bytes_sent;
- togo -= bytes_sent; /* track how much of the file we've sent */
- }
- }
- }
-
- /* Send the trailers
- * XXX: optimization... if it will fit, send this on the last send in the
- * loop above
- */
- sendlen = 0;
- if ( rv == APR_SUCCESS && hdtr && hdtr->numtrailers > 0 ) {
- for (i = 0; i < hdtr->numtrailers; i++) {
- sendlen += hdtr->trailers[i].iov_len;
- }
- rv = writev_it_all(c->client_socket, hdtr->trailers, hdtr->numtrailers,
- sendlen, &bytes_sent);
- if (rv == APR_SUCCESS)
- *nbytes += bytes_sent;
- }
-
- return rv;
-}
-
-/* Note --- ErrorDocument will now work from .htaccess files.
- * The AllowOverride of Fileinfo allows webmasters to turn it off
- */
-
-static const command_rec core_cmds[] = {
-
-/* Old access config file commands */
-
-AP_INIT_RAW_ARGS("<Directory", dirsection, NULL, RSRC_CONF,
- "Container for directives affecting resources located in the specified "
- "directories"),
-AP_INIT_RAW_ARGS("<Location", urlsection, NULL, RSRC_CONF,
- "Container for directives affecting resources accessed through the "
- "specified URL paths"),
-AP_INIT_RAW_ARGS("<VirtualHost", virtualhost_section, NULL, RSRC_CONF,
- "Container to map directives to a particular virtual host, takes one or "
- "more host addresses"),
-AP_INIT_RAW_ARGS("<Files", filesection, NULL, OR_ALL,
- "Container for directives affecting files matching specified patterns"),
-AP_INIT_RAW_ARGS("<Limit", ap_limit_section, NULL, OR_ALL,
- "Container for authentication directives when accessed using specified HTTP "
- "methods"),
-AP_INIT_RAW_ARGS("<LimitExcept", ap_limit_section, (void*)1, OR_ALL,
- "Container for authentication directives to be applied when any HTTP "
- "method other than those specified is used to access the resource"),
-AP_INIT_TAKE1("<IfModule", start_ifmod, NULL, EXEC_ON_READ | OR_ALL,
- "Container for directives based on existance of specified modules"),
-AP_INIT_TAKE1("<IfDefine", start_ifdefine, NULL, EXEC_ON_READ | OR_ALL,
- "Container for directives based on existance of command line defines"),
-AP_INIT_RAW_ARGS("<DirectoryMatch", dirsection, (void*)1, RSRC_CONF,
- "Container for directives affecting resources located in the "
- "specified directories"),
-AP_INIT_RAW_ARGS("<LocationMatch", urlsection, (void*)1, RSRC_CONF,
- "Container for directives affecting resources accessed through the "
- "specified URL paths"),
-AP_INIT_RAW_ARGS("<FilesMatch", filesection, (void*)1, OR_ALL,
- "Container for directives affecting files matching specified patterns"),
-AP_INIT_TAKE1("AuthType", ap_set_string_slot,
- (void*)XtOffsetOf(core_dir_config, ap_auth_type), OR_AUTHCFG,
- "An HTTP authorization type (e.g., \"Basic\")"),
-AP_INIT_TAKE1("AuthName", set_authname, NULL, OR_AUTHCFG,
- "The authentication realm (e.g. \"Members Only\")"),
-AP_INIT_RAW_ARGS("Require", require, NULL, OR_AUTHCFG,
- "Selects which authenticated users or groups may access a protected space"),
-AP_INIT_TAKE1("Satisfy", satisfy, NULL, OR_AUTHCFG,
- "access policy if both allow and require used ('all' or 'any')"),
-#ifdef GPROF
-AP_INIT_TAKE1("GprofDir", set_gprof_dir, NULL, RSRC_CONF,
- "Directory to plop gmon.out files"),
-#endif
-AP_INIT_TAKE1("AddDefaultCharset", set_add_default_charset, NULL, OR_FILEINFO,
- "The name of the default charset to add to any Content-Type without one or 'Off' to disable"),
-
-/* Old resource config file commands */
-
-AP_INIT_RAW_ARGS("AccessFileName", set_access_name, NULL, RSRC_CONF,
- "Name(s) of per-directory config files (default: .htaccess)"),
-AP_INIT_TAKE1("DocumentRoot", set_document_root, NULL, RSRC_CONF,
- "Root directory of the document tree"),
-AP_INIT_TAKE2("ErrorDocument", set_error_document, NULL, OR_FILEINFO,
- "Change responses for HTTP errors"),
-AP_INIT_RAW_ARGS("AllowOverride", set_override, NULL, ACCESS_CONF,
- "Controls what groups of directives can be configured by per-directory "
- "config files"),
-AP_INIT_RAW_ARGS("Options", set_options, NULL, OR_OPTIONS,
- "Set a number of attributes for a given directory"),
-AP_INIT_TAKE1("DefaultType", ap_set_string_slot,
- (void*)XtOffsetOf (core_dir_config, ap_default_type),
- OR_FILEINFO, "the default MIME type for untypable files"),
-
-/* Old server config file commands */
-
-AP_INIT_TAKE1("Port", server_port, NULL, RSRC_CONF, "A TCP port number"),
-AP_INIT_TAKE1("HostnameLookups", set_hostname_lookups, NULL,
- ACCESS_CONF|RSRC_CONF,
- "\"on\" to enable, \"off\" to disable reverse DNS lookups, or \"double\" to "
- "enable double-reverse DNS lookups"),
-AP_INIT_TAKE1("ServerAdmin", set_server_string_slot,
- (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF,
- "The email address of the server administrator"),
-AP_INIT_TAKE1("ServerName", set_server_string_slot,
- (void *)XtOffsetOf (server_rec, server_hostname), RSRC_CONF,
- "The hostname of the server"),
-AP_INIT_TAKE1("ServerSignature", set_signature_flag, NULL, OR_ALL,
- "En-/disable server signature (on|off|email)"),
-AP_INIT_TAKE1("ServerRoot", set_server_root, NULL, RSRC_CONF,
- "Common directory of server-related files (logs, confs, etc.)"),
-AP_INIT_TAKE1("ErrorLog", set_server_string_slot,
- (void *)XtOffsetOf (server_rec, error_fname), RSRC_CONF,
- "The filename of the error log"),
-AP_INIT_RAW_ARGS("ServerAlias", set_server_alias, NULL, RSRC_CONF,
- "A name or names alternately used to access the server"),
-AP_INIT_TAKE1("ServerPath", set_serverpath, NULL, RSRC_CONF,
- "The pathname the server can be reached at"),
-AP_INIT_TAKE1("Timeout", set_timeout, NULL, RSRC_CONF,
- "Timeout duration (sec)"),
-AP_INIT_FLAG("IdentityCheck", set_idcheck, NULL, RSRC_CONF|ACCESS_CONF,
- "Enable identd (RFC 1413) user lookups - SLOW"),
-AP_INIT_FLAG("ContentDigest", set_content_md5, NULL, OR_OPTIONS,
- "whether or not to send a Content-MD5 header with each request"),
-AP_INIT_TAKE1("UseCanonicalName", set_use_canonical_name, NULL,
- RSRC_CONF|ACCESS_CONF,
- "How to work out the ServerName : Port when constructing URLs"),
-/* TODO: RlimitFoo should all be part of mod_cgi, not in the core */
-/* TODO: ListenBacklog in MPM */
-AP_INIT_TAKE1("Include", include_config, NULL,
- (RSRC_CONF | ACCESS_CONF | EXEC_ON_READ),
- "Name of the config file to be included"),
-AP_INIT_TAKE1("LogLevel", set_loglevel, NULL, RSRC_CONF,
- "Level of verbosity in error logging"),
-AP_INIT_TAKE1("NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF,
- "A numeric IP address:port, or the name of a host"),
-#ifdef _OSD_POSIX
-AP_INIT_TAKE1("BS2000Account", set_bs2000_account, NULL, RSRC_CONF,
- "Name of server User's bs2000 logon account name"),
-#endif
-#ifdef WIN32
-AP_INIT_TAKE1("ScriptInterpreterSource", set_interpreter_source, NULL,
- OR_FILEINFO,
- "Where to find interpreter to run Win32 scripts (Registry or script shebang line)"),
-#endif
-AP_INIT_TAKE1("ServerTokens", set_serv_tokens, NULL, RSRC_CONF,
- "Determine tokens displayed in the Server: header - Min(imal), OS or Full"),
-AP_INIT_TAKE1("LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF,
- "Limit on maximum size of an HTTP request line"),
-AP_INIT_TAKE1("LimitRequestFieldsize", set_limit_req_fieldsize, NULL,
- RSRC_CONF,
- "Limit on maximum size of an HTTP request header field"),
-AP_INIT_TAKE1("LimitRequestFields", set_limit_req_fields, NULL, RSRC_CONF,
- "Limit (0 = unlimited) on max number of header fields in a request message"),
-AP_INIT_TAKE1("LimitRequestBody", set_limit_req_body,
- (void*)XtOffsetOf(core_dir_config, limit_req_body), OR_ALL,
- "Limit (in bytes) on maximum size of request message body"),
-AP_INIT_TAKE1("LimitXMLRequestBody", set_limit_xml_req_body, NULL, OR_ALL,
- "Limit (in bytes) on maximum size of an XML-based request "
- "body"),
-
-/* System Resource Controls */
-#ifdef RLIMIT_CPU
-AP_INIT_TAKE12("RLimitCPU", set_limit_cpu,
- (void*)XtOffsetOf(core_dir_config, limit_cpu),
- OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
-#else
-AP_INIT_TAKE12("RLimitCPU", no_set_limit, NULL,
- OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
-#endif
-#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
-AP_INIT_TAKE12("RLimitMEM", set_limit_mem,
- (void*)XtOffsetOf(core_dir_config, limit_mem),
- OR_ALL, "Soft/hard limits for max memory usage per process"),
-#else
-AP_INIT_TAKE12("RLimitMEM", no_set_limit, NULL,
- OR_ALL, "Soft/hard limits for max memory usage per process"),
-#endif
-#ifdef RLIMIT_NPROC
-AP_INIT_TAKE12("RLimitNPROC", set_limit_nproc,
- (void*)XtOffsetOf(core_dir_config, limit_nproc),
- OR_ALL, "soft/hard limits for max number of processes per uid"),
-#else
-AP_INIT_TAKE12("RLimitNPROC", no_set_limit, NULL,
- OR_ALL, "soft/hard limits for max number of processes per uid"),
-#endif
-/* XXX These should be allowable in .htaccess files, but currently it won't
- * play well with the Options stuff. Until that is fixed, I would prefer
- * to leave it just in the conf file. Other should feel free to disagree
- * with me. Rbb.
- */
-AP_INIT_ITERATE("SetOutputFilter", add_filter, NULL, ACCESS_CONF,
- "filters to be run"),
-AP_INIT_ITERATE("SetInputFilter", add_input_filter, NULL, ACCESS_CONF,
- "filters to be run on the request body"),
-{ NULL }
-};
-
-/*****************************************************************
- *
- * Core handlers for various phases of server operation...
- */
-
-AP_DECLARE_NONSTD(int) ap_core_translate(request_rec *r)
-{
- void *sconf = r->server->module_config;
- core_server_config *conf = ap_get_module_config(sconf, &core_module);
-
- if (r->proxyreq) {
- return HTTP_FORBIDDEN;
- }
- if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid URI in request %s", r->the_request);
- return HTTP_BAD_REQUEST;
- }
-
- if (r->server->path
- && !strncmp(r->uri, r->server->path, r->server->pathlen)
- && (r->server->path[r->server->pathlen - 1] == '/'
- || r->uri[r->server->pathlen] == '/'
- || r->uri[r->server->pathlen] == '\0')) {
- r->filename = apr_pstrcat(r->pool, conf->ap_document_root,
- (r->uri + r->server->pathlen), NULL);
- }
- else {
- /*
- * Make sure that we do not mess up the translation by adding two
- * /'s in a row. This happens under windows when the document
- * root ends with a /
- */
- if ((conf->ap_document_root[strlen(conf->ap_document_root)-1] == '/')
- && (*(r->uri) == '/')) {
- r->filename = apr_pstrcat(r->pool, conf->ap_document_root, r->uri+1,
- NULL);
- }
- else {
- r->filename = apr_pstrcat(r->pool, conf->ap_document_root, r->uri,
- NULL);
- }
- }
-
- return OK;
-}
-
-static int do_nothing(request_rec *r) { return OK; }
-
-static int default_handler(request_rec *r)
-{
- apr_bucket_brigade *bb;
- apr_bucket *e;
- core_dir_config *d;
- int errstatus;
- apr_file_t *fd = NULL;
- apr_status_t status;
- /* XXX if/when somebody writes a content-md5 filter we either need to
- * remove this support or coordinate when to use the filter vs.
- * when to use this code
- * The current choice of when to compute the md5 here matches the 1.3
- * support fairly closely (unlike 1.3, we don't handle computing md5
- * when the charset is translated).
- */
- int bld_content_md5;
-
- /*
- * The old way of doing handlers meant that this handler would
- * match literally anything - this way will require handler to
- * have a / in the middle, which probably captures the original
- * intent, but may cause problems at first - Ben 7th Jan 01
- */
- if(strcmp(r->handler,"default-handler")
- && ap_strcmp_match(r->handler,"*/*"))
- return DECLINED;
-
- d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- bld_content_md5 = (d->content_md5 & 1)
- && r->output_filters->frec->ftype != AP_FTYPE_CONTENT;
-
- ap_allow_methods(r, MERGE_ALLOW, "GET", "OPTIONS", "POST", NULL);
-
- if ((errstatus = ap_discard_request_body(r)) != OK) {
- return errstatus;
- }
-
- if (r->method_number == M_INVALID) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid method in request %s", r->the_request);
- return HTTP_NOT_IMPLEMENTED;
- }
- if (r->method_number == M_OPTIONS) {
- return ap_send_http_options(r);
- }
- if (r->method_number == M_PUT) {
- return HTTP_METHOD_NOT_ALLOWED;
- }
- if (r->finfo.filetype == 0 || (r->path_info && *r->path_info)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
- "File does not exist: %s",r->path_info ?
- apr_pstrcat(r->pool, r->filename, r->path_info, NULL)
- : r->filename);
- return HTTP_NOT_FOUND;
- }
-
- if (r->method_number != M_GET && r->method_number != M_POST) {
- return HTTP_METHOD_NOT_ALLOWED;
- }
-
- if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY, 0, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
- "file permissions deny server access: %s", r->filename);
- return HTTP_FORBIDDEN;
- }
- ap_update_mtime(r, r->finfo.mtime);
- ap_set_last_modified(r);
- ap_set_etag(r);
- apr_table_setn(r->headers_out, "Accept-Ranges", "bytes");
- ap_set_content_length(r, r->finfo.size);
- if ((errstatus = ap_meets_conditions(r)) != OK) {
- apr_file_close(fd);
- return errstatus;
- }
-
- if (bld_content_md5) {
- apr_table_setn(r->headers_out, "Content-MD5",
- ap_md5digest(r->pool, fd));
- }
-
- bb = apr_brigade_create(r->pool);
- e = apr_bucket_file_create(fd, 0, r->finfo.size);
-
- APR_BRIGADE_INSERT_HEAD(bb, e);
- e = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
-
- return ap_pass_brigade(r->output_filters, bb);
-}
-
-static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_bucket *e;
-
- if (!f->ctx) { /* If we haven't passed up the socket yet... */
- f->ctx = (void *)1;
- e = apr_bucket_socket_create(f->c->client_socket);
- APR_BRIGADE_INSERT_TAIL(b, e);
- return APR_SUCCESS;
- }
- else {
- /* Either some code lost track of the socket
- * bucket or we already found out that the
- * client closed.
- */
- return APR_EOF;
- }
-}
-
-/* Default filter. This filter should almost always be used. Its only job
- * is to send the headers if they haven't already been sent, and then send
- * the actual data.
- */
-typedef struct CORE_OUTPUT_FILTER_CTX {
- apr_bucket_brigade *b;
-} core_output_filter_ctx_t;
-
-#define MAX_IOVEC_TO_WRITE 16
-
-static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
-{
- apr_status_t rv;
- conn_rec *c = f->c;
- core_output_filter_ctx_t *ctx = f->ctx;
-
- if (ctx == NULL) {
- f->ctx = ctx = apr_pcalloc(c->pool, sizeof(core_output_filter_ctx_t));
- }
-
- /* If we have a saved brigade, concatenate the new brigade to it */
- if (ctx->b) {
- APR_BRIGADE_CONCAT(ctx->b, b);
- b = ctx->b;
- ctx->b = NULL;
- }
-
- /* Perform multiple passes over the brigade, sending batches of output
- to the connection. */
- while (b) {
- apr_size_t nbytes = 0;
- apr_bucket *e;
-
- /* tail of brigade if we need another pass */
- apr_bucket_brigade *more = NULL;
-
- /* one group of iovecs per pass over the brigade */
- apr_size_t nvec = 0;
- apr_size_t nvec_trailers = 0;
- struct iovec vec[MAX_IOVEC_TO_WRITE];
- struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
-
- /* one file per pass over the brigade */
- apr_file_t *fd = NULL;
- apr_size_t flen = 0;
- apr_off_t foffset = 0;
-
- /* Iterate over the brigade: collect iovecs and/or a file */
- APR_BRIGADE_FOREACH(e, b) {
- if (APR_BUCKET_IS_EOS(e) || APR_BUCKET_IS_FLUSH(e)) {
- break;
- }
- /* It doesn't make any sense to use sendfile for a file bucket
- * that represents 10 bytes.
- */
- else if (APR_BUCKET_IS_FILE(e)
- && (e->length >= AP_MIN_SENDFILE_BYTES)) {
- apr_bucket_file *a = e->data;
-
- /* We can't handle more than one file bucket at a time
- * so we split here and send the file we have already
- * found.
- */
- if (fd) {
- more = apr_brigade_split(b, e);
- break;
- }
-
- fd = a->fd;
- flen = e->length;
- foffset = e->start;
- }
- else {
- const char *str;
- apr_size_t n;
-
- rv = apr_bucket_read(e, &str, &n, APR_BLOCK_READ);
- if (n) {
- if (!fd) {
- if (nvec == MAX_IOVEC_TO_WRITE) {
- /* woah! too many. stop now. */
- more = apr_brigade_split(b, e);
- break;
- }
- vec[nvec].iov_base = (char*) str;
- vec[nvec].iov_len = n;
- nvec++;
- }
- else {
- /* The bucket is a trailer to a file bucket */
-
- if (nvec_trailers == MAX_IOVEC_TO_WRITE) {
- /* woah! too many. stop now. */
- more = apr_brigade_split(b, e);
- break;
- }
- vec_trailers[nvec_trailers].iov_base = (char*) str;
- vec_trailers[nvec_trailers].iov_len = n;
- nvec_trailers++;
- }
- nbytes += n;
- }
- }
- }
-
- /* Completed iterating over the brigades, now determine if we want
- * to buffer the brigade or send the brigade out on the network.
- *
- * Save if:
- *
- * 1) we didn't see a file, we don't have more passes over the
- * brigade to perform, we haven't accumulated enough bytes to
- * send, AND we didn't stop at a FLUSH bucket.
- * (IOW, we will save away plain old bytes)
- * or
- * 2) we hit the EOS and have a keep-alive connection
- * (IOW, this response is a bit more complex, but we save it
- * with the hope of concatenating with another response)
- */
- if ((!fd && !more &&
- (nbytes + flen < AP_MIN_BYTES_TO_WRITE) && !APR_BUCKET_IS_FLUSH(e))
- || (nbytes + flen < AP_MIN_BYTES_TO_WRITE && APR_BUCKET_IS_EOS(e) && c->keepalive)) {
- /* NEVER save an EOS in here. If we are saving a brigade with
- * an EOS bucket, then we are doing keepalive connections, and
- * we want to process to second request fully.
- */
- if (APR_BUCKET_IS_EOS(e)) {
- apr_bucket *bucket = NULL;
- /* If we are in here, then this request is a keepalive. We
- * need to be certain that any data in a bucket is valid
- * after the request_pool is cleared.
- */
- if (ctx->b == NULL) {
- ctx->b = apr_brigade_create(f->c->pool);
- }
-
- APR_BRIGADE_FOREACH(bucket, b) {
- const char *str;
- apr_size_t n;
-
- rv = apr_bucket_read(bucket, &str, &n, APR_BLOCK_READ);
-
- /* This apr_brigade_write does not use a flush function
- because we assume that we will not write enough data
- into it to cause a flush. However, if we *do* write
- "too much", then we could end up with transient
- buckets which would suck. This works for now, but is
- a bit shaky if changes are made to some of the
- buffering sizes. Let's do an assert to prevent
- potential future problems... */
- AP_DEBUG_ASSERT(AP_MIN_BYTES_TO_WRITE <=
- APR_BUCKET_BUFF_SIZE);
- apr_brigade_write(ctx->b, NULL, NULL, str, n);
- }
- apr_brigade_destroy(b);
- }
- else {
- ap_save_brigade(f, &ctx->b, &b);
- }
- return APR_SUCCESS;
- }
-
- if (fd) {
- apr_hdtr_t hdtr;
-#if APR_HAS_SENDFILE
- apr_int32_t flags = 0;
-#endif
-
- memset(&hdtr, '\0', sizeof(hdtr));
- if (nvec) {
- hdtr.numheaders = nvec;
- hdtr.headers = vec;
- }
- if (nvec_trailers) {
- hdtr.numtrailers = nvec_trailers;
- hdtr.trailers = vec_trailers;
- }
-#if APR_HAS_SENDFILE
- if (!c->keepalive) {
- /* Prepare the socket to be reused */
- flags |= APR_SENDFILE_DISCONNECT_SOCKET;
- }
- rv = sendfile_it_all(c, /* the connection */
- fd, /* the file to send */
- &hdtr, /* header and trailer iovecs */
- foffset, /* offset in the file to begin
- sending from */
- flen, /* length of file */
- nbytes + flen, /* total length including
- headers */
- flags); /* apr_sendfile flags */
-
- /* If apr_sendfile() returns APR_ENOTIMPL, call send_the_file()
- * to loop on apr_file_read/apr_send to send the file. Our Windows
- * binary distributions (which work on Windows 9x/NT) are
- * compiled on Windows NT. TransmitFile is not available on
- * Windows 95/98 and we discover this at runtime when
- * apr_sendfile() returns APR_ENOTIMPL. Having apr_sendfile()
- * return APR_ENOTIMPL seems the cleanest way to handle this
- * case.
- */
- if (rv == APR_ENOTIMPL)
-#endif
- {
- apr_size_t unused_bytes_sent;
-
- rv = send_the_file(c, fd, &hdtr, foffset, flen,
- &unused_bytes_sent);
- }
- fd = NULL;
- }
- else {
- apr_size_t unused_bytes_sent;
-
- rv = writev_it_all(c->client_socket,
- vec, nvec,
- nbytes, &unused_bytes_sent);
- }
-
- apr_brigade_destroy(b);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
- "core_output_filter: writing data to the network");
- if (more)
- apr_brigade_destroy(more);
- if (APR_STATUS_IS_ECONNABORTED(rv) ||
- APR_STATUS_IS_ECONNRESET(rv)) {
- c->aborted = 1;
- }
- return rv;
- }
-
- b = more;
- more = NULL;
- } /* end while () */
-
- return APR_SUCCESS;
-}
-
-static void core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
-{
- ap_set_version(pconf);
-}
-
-static void core_open_logs(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
-{
- ap_open_logs(s, pconf);
-}
-
-static void core_insert_filter(request_rec *r)
-{
- int i;
- core_dir_config *conf = (core_dir_config *)
- ap_get_module_config(r->per_dir_config,
- &core_module);
- char **items = (char **)conf->output_filters->elts;
-
- for (i = 0; i < conf->output_filters->nelts; i++) {
- char *foobar = items[i];
- ap_add_output_filter(foobar, NULL, r, r->connection);
- }
-
- items = (char **)conf->input_filters->elts;
- for (i = 0; i < conf->input_filters->nelts; i++) {
- char *foobar = items[i];
- ap_add_input_filter(foobar, NULL, r, r->connection);
- }
-}
-
-static int core_create_req(request_rec *r)
-{
- if (r->main) {
- ap_set_module_config(r->request_config, &core_module,
- ap_get_module_config(r->main->request_config, &core_module));
- }
- else {
- core_request_config *req_cfg;
-
- req_cfg = apr_pcalloc(r->pool, sizeof(core_request_config));
- req_cfg->bb = apr_brigade_create(r->pool);
- ap_set_module_config(r->request_config, &core_module, req_cfg);
- }
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_post_config(core_post_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
- ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST);
- ap_hook_open_logs(core_open_logs,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_handler(default_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
- /* FIXME: I suspect we can eliminate the need for these - Ben */
- ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
- ap_hook_access_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
- ap_hook_create_request(core_create_req, NULL, NULL, APR_HOOK_MIDDLE);
-
- /* register the core's insert_filter hook and register core-provided
- * filters
- */
- ap_hook_insert_filter(core_insert_filter, NULL, NULL, APR_HOOK_MIDDLE);
-
- ap_register_input_filter("CORE_IN", core_input_filter, AP_FTYPE_NETWORK);
- ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter,
- AP_FTYPE_HTTP_HEADER);
- ap_register_output_filter("CORE", core_output_filter, AP_FTYPE_NETWORK);
- ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter,
- AP_FTYPE_CONTENT);
- ap_register_output_filter("OLD_WRITE", ap_old_write_filter,
- AP_FTYPE_CONTENT - 1);
-}
-
-AP_DECLARE_DATA module core_module = {
- STANDARD20_MODULE_STUFF,
- create_core_dir_config, /* create per-directory config structure */
- merge_core_dir_configs, /* merge per-directory config structures */
- create_core_server_config, /* create per-server config structure */
- merge_core_server_configs, /* merge per-server config structures */
- core_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/server/error_bucket.c b/server/error_bucket.c
deleted file mode 100644
index 7a786ff4d8..0000000000
--- a/server/error_bucket.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "http_protocol.h"
-#include "apr_buckets.h"
-#include "apr_strings.h"
-#include <stdlib.h>
-#if APR_HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-static apr_status_t error_read(apr_bucket *b, const char **str,
- apr_size_t *len, apr_read_type_e block)
-{
- *str = NULL;
- *len = 0;
- return APR_SUCCESS;
-}
-
-AP_DECLARE(apr_bucket *) ap_bucket_error_make(apr_bucket *b, int error,
- const char *buf, apr_pool_t *p)
-{
- ap_bucket_error *h;
-
- h = malloc(sizeof(*h));
- if (h == NULL) {
- return NULL;
- }
- h->status = error;
- h->data = (buf) ? apr_pstrdup(p, buf) : NULL;
-
- b->length = 0;
- b->start = 0;
- b->type = &ap_bucket_type_error;
- b->data = h;
- return b;
-}
-
-AP_DECLARE(apr_bucket *) ap_bucket_error_create(int error,
- const char *buf, apr_pool_t *p)
-{
- apr_bucket *b = (apr_bucket *)calloc(1, sizeof(*b));
-
- APR_BUCKET_INIT(b);
- return ap_bucket_error_make(b, error, buf, p);
-}
-
-AP_DECLARE_DATA const apr_bucket_type_t ap_bucket_type_error = {
- "ERROR", 5,
- free,
- error_read,
- apr_bucket_setaside_notimpl,
- apr_bucket_split_notimpl,
- apr_bucket_copy_notimpl
-};
diff --git a/server/gen_test_char.c b/server/gen_test_char.c
deleted file mode 100644
index 5bc1f97f01..0000000000
--- a/server/gen_test_char.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_lib.h"
-
-#if APR_HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-/* we need some of the portability definitions... for strchr */
-#include "ap_config.h"
-#include "httpd.h"
-
-/* A bunch of functions in util.c scan strings looking for certain characters.
- * To make that more efficient we encode a lookup table.
- */
-#define T_ESCAPE_SHELL_CMD (0x01)
-#define T_ESCAPE_PATH_SEGMENT (0x02)
-#define T_OS_ESCAPE_PATH (0x04)
-#define T_HTTP_TOKEN_STOP (0x08)
-
-int main(int argc, char *argv[])
-{
- unsigned c;
- unsigned char flags;
-
- printf(
-"/* this file is automatically generated by gen_test_char, do not edit */\n"
-"#define T_ESCAPE_SHELL_CMD (%u)\n"
-"#define T_ESCAPE_PATH_SEGMENT (%u)\n"
-"#define T_OS_ESCAPE_PATH (%u)\n"
-"#define T_HTTP_TOKEN_STOP (%u)\n"
-"\n"
-"static const unsigned char test_char_table[256] = {\n"
-" 0,",
- T_ESCAPE_SHELL_CMD,
- T_ESCAPE_PATH_SEGMENT,
- T_OS_ESCAPE_PATH,
- T_HTTP_TOKEN_STOP);
-
- /* we explicitly dealt with NUL above
- * in case some strchr() do bogosity with it */
-
- for (c = 1; c < 256; ++c) {
- flags = 0;
- if (c % 20 == 0)
- printf("\n ");
-
- /* escape_shell_cmd */
- if (strchr("&;`'\"|*?~<>^()[]{}$\\\n", c)) {
- flags |= T_ESCAPE_SHELL_CMD;
- }
-
- if (!apr_isalnum(c) && !strchr("$-_.+!*'(),:@&=~", c)) {
- flags |= T_ESCAPE_PATH_SEGMENT;
- }
-
- if (!apr_isalnum(c) && !strchr("$-_.+!*'(),:@&=/~", c)) {
- flags |= T_OS_ESCAPE_PATH;
- }
-
- /* these are the "tspecials" from RFC2068 */
- if (apr_iscntrl(c) || strchr(" \t()<>@,;:\\/[]?={}", c)) {
- flags |= T_HTTP_TOKEN_STOP;
- }
- printf("%u%c", flags, (c < 255) ? ',' : ' ');
-
- }
- printf("\n};\n");
-
- return 0;
-}
diff --git a/server/gen_test_char.dsp b/server/gen_test_char.dsp
deleted file mode 100644
index 26c12386db..0000000000
--- a/server/gen_test_char.dsp
+++ /dev/null
@@ -1,90 +0,0 @@
-# Microsoft Developer Studio Project File - Name="gen_test_char" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=gen_test_char - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "gen_test_char.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "gen_test_char.mak" CFG="gen_test_char - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "gen_test_char - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "gen_test_char - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "gen_test_char - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir ""
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ""
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\include" /I "..\srclib\apr\include" /I "..\srclib\apr-util\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Release\gen_test_char" /FD /c
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Release\gen_test_char.pdb" /machine:I386
-# ADD LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Release\gen_test_char.pdb" /machine:I386
-
-!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir ""
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ""
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\include" /I "..\srclib\apr\include" /I "..\srclib\apr-util\include" /I "..\os\win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Debug\gen_test_char" /FD /c
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_test_char.pdb" /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_test_char.pdb" /debug /machine:I386
-
-!ENDIF
-
-# Begin Target
-
-# Name "gen_test_char - Win32 Release"
-# Name "gen_test_char - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\gen_test_char.c
-# End Source File
-# End Target
-# End Project
diff --git a/server/gen_test_char.mak b/server/gen_test_char.mak
deleted file mode 100644
index c884e79eb4..0000000000
--- a/server/gen_test_char.mak
+++ /dev/null
@@ -1,300 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on gen_test_char.dsp
-!IF "$(CFG)" == ""
-CFG=gen_test_char - Win32 Debug
-!MESSAGE No configuration specified. Defaulting to gen_test_char - Win32 Debug.
-!ENDIF
-
-!IF "$(CFG)" != "gen_test_char - Win32 Release" && "$(CFG)" !=\
- "gen_test_char - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "gen_test_char.mak" CFG="gen_test_char - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "gen_test_char - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "gen_test_char - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "gen_test_char - Win32 Release"
-
-OUTDIR=.
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\gen_test_char.exe"
-
-!ELSE
-
-ALL : "aprutil - Win32 Release" "apr - Win32 Release"\
- "$(OUTDIR)\gen_test_char.exe"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"apr - Win32 ReleaseCLEAN" "aprutil - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\gen_test_char.idb"
- -@erase "$(INTDIR)\gen_test_char.obj"
- -@erase "$(OUTDIR)\gen_test_char.exe"
-
-"$(INTDIR)" :
- if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\include" /I "..\srclib\apr\include" /I\
- "..\srclib\apr-util\include" /I "..\os\win32" /D "WIN32" /D "NDEBUG" /D\
- "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\gen_test_char" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:console /incremental:no\
- /pdb:"$(OUTDIR)\Release\gen_test_char.pdb" /machine:I386\
- /out:"$(OUTDIR)\gen_test_char.exe"
-LINK32_OBJS= \
- "$(INTDIR)\gen_test_char.obj" \
- "..\srclib\apr-util\LibR\aprutil.lib" \
- "..\srclib\apr\LibR\apr.lib"
-
-"$(OUTDIR)\gen_test_char.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug"
-
-OUTDIR=.
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\gen_test_char.exe"
-
-!ELSE
-
-ALL : "aprutil - Win32 Debug" "apr - Win32 Debug" "$(OUTDIR)\gen_test_char.exe"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"apr - Win32 DebugCLEAN" "aprutil - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\gen_test_char.idb"
- -@erase "$(INTDIR)\gen_test_char.obj"
- -@erase "$(OUTDIR)\Debug\gen_test_char.pdb"
- -@erase "$(OUTDIR)\gen_test_char.exe"
-
-"$(INTDIR)" :
- if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\include" /I\
- "..\srclib\apr\include" /I "..\srclib\apr-util\include" /I "..\os\win32" /D\
- "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"$(INTDIR)\\"\
- /Fd"$(INTDIR)\gen_test_char" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:console /incremental:no\
- /pdb:"$(OUTDIR)\Debug\gen_test_char.pdb" /debug /machine:I386\
- /out:"$(OUTDIR)\gen_test_char.exe"
-LINK32_OBJS= \
- "$(INTDIR)\gen_test_char.obj" \
- "..\srclib\apr-util\LibD\aprutil.lib" \
- "..\srclib\apr\LibD\apr.lib"
-
-"$(OUTDIR)\gen_test_char.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "gen_test_char - Win32 Release" || "$(CFG)" ==\
- "gen_test_char - Win32 Debug"
-
-!IF "$(CFG)" == "gen_test_char - Win32 Release"
-
-"apr - Win32 Release" :
- cd "..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\apr.mak CFG="apr - Win32 Release"
- cd "..\..\server"
-
-"apr - Win32 ReleaseCLEAN" :
- cd "..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\apr.mak CFG="apr - Win32 Release" RECURSE=1\
-
- cd "..\..\server"
-
-!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug"
-
-"apr - Win32 Debug" :
- cd "..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\apr.mak CFG="apr - Win32 Debug"
- cd "..\..\server"
-
-"apr - Win32 DebugCLEAN" :
- cd "..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\apr.mak CFG="apr - Win32 Debug" RECURSE=1
- cd "..\..\server"
-
-!ENDIF
-
-!IF "$(CFG)" == "gen_test_char - Win32 Release"
-
-"aprutil - Win32 Release" :
- cd "..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\aprutil.mak" CFG="aprutil - Win32 Release"
- cd "..\..\server"
-
-"aprutil - Win32 ReleaseCLEAN" :
- cd "..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\aprutil.mak" CFG="aprutil - Win32 Release"\
- RECURSE=1
- cd "..\..\server"
-
-!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug"
-
-"aprutil - Win32 Debug" :
- cd "..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\aprutil.mak" CFG="aprutil - Win32 Debug"
- cd "..\..\server"
-
-"aprutil - Win32 DebugCLEAN" :
- cd "..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\aprutil.mak" CFG="aprutil - Win32 Debug"\
- RECURSE=1
- cd "..\..\server"
-
-!ENDIF
-
-SOURCE=.\gen_test_char.c
-DEP_CPP_GEN_T=\
- "..\include\ap_config.h"\
- "..\include\ap_mmn.h"\
- "..\include\ap_release.h"\
- "..\include\httpd.h"\
- "..\include\pcreposix.h"\
- "..\include\util_uri.h"\
- "..\os\win32\os.h"\
- "..\srclib\apr-util\include\apr_hooks.h"\
- "..\srclib\apr-util\include\apu.h"\
- "..\srclib\apr\include\apr.h"\
- "..\srclib\apr\include\apr_errno.h"\
- "..\srclib\apr\include\apr_file_info.h"\
- "..\srclib\apr\include\apr_file_io.h"\
- "..\srclib\apr\include\apr_general.h"\
- "..\srclib\apr\include\apr_lib.h"\
- "..\srclib\apr\include\apr_network_io.h"\
- "..\srclib\apr\include\apr_pools.h"\
- "..\srclib\apr\include\apr_tables.h"\
- "..\srclib\apr\include\apr_time.h"\
- "..\srclib\apr\include\apr_user.h"\
- "..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_GEN_T=\
- "..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\gen_test_char.obj" : $(SOURCE) $(DEP_CPP_GEN_T) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/server/gen_uri_delims.c b/server/gen_uri_delims.c
deleted file mode 100644
index df82916083..0000000000
--- a/server/gen_uri_delims.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include <stdio.h>
-
-/* generate a apr_table_t of 256 values, where certain characters are
- * marked "interesting"... for the uri parsing process.
- */
-
-int main(int argc, char *argv[])
-{
- int i;
- char *value;
-
- printf("/* this file is automatically generated by "
- "gen_uri_delims, do not edit */\n");
- printf("static const unsigned char uri_delims[256] = {");
- for (i = 0; i < 256; ++i) {
- if (i % 20 == 0)
- printf("\n ");
- switch (i) {
- case ':': value = "T_COLON"; break;
- case '/': value = "T_SLASH"; break;
- case '?': value = "T_QUESTION"; break;
- case '#': value = "T_HASH"; break;
- case '\0': value = "T_NUL"; break;
- default: value = "0"; break;
- }
- printf("%s%c", value, (i < 255) ? ',' : ' ');
- }
- printf("\n};\n");
-
- return 0;
-}
diff --git a/server/gen_uri_delims.dsp b/server/gen_uri_delims.dsp
deleted file mode 100644
index fafe5bfea0..0000000000
--- a/server/gen_uri_delims.dsp
+++ /dev/null
@@ -1,90 +0,0 @@
-# Microsoft Developer Studio Project File - Name="gen_uri_delims" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=gen_uri_delims - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "gen_uri_delims.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "gen_uri_delims - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "gen_uri_delims - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "gen_uri_delims - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir ""
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ""
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Release\gen_uri_delims" /FD /c
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Release\gen_uri_delims.pdb" /machine:I386
-# ADD LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Release\gen_uri_delims.pdb" /machine:I386
-
-!ELSEIF "$(CFG)" == "gen_uri_delims - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir ""
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ""
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Debug\gen_uri_delims" /FD /c
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_uri_delims.pdb" /debug /machine:I386
-# ADD LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_uri_delims.pdb" /debug /machine:I386
-
-!ENDIF
-
-# Begin Target
-
-# Name "gen_uri_delims - Win32 Release"
-# Name "gen_uri_delims - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\gen_uri_delims.c
-# End Source File
-# End Target
-# End Project
diff --git a/server/gen_uri_delims.mak b/server/gen_uri_delims.mak
deleted file mode 100644
index 5084add7e0..0000000000
--- a/server/gen_uri_delims.mak
+++ /dev/null
@@ -1,203 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on gen_uri_delims.dsp
-!IF "$(CFG)" == ""
-CFG=gen_uri_delims - Win32 Debug
-!MESSAGE No configuration specified. Defaulting to gen_uri_delims - Win32\
- Debug.
-!ENDIF
-
-!IF "$(CFG)" != "gen_uri_delims - Win32 Release" && "$(CFG)" !=\
- "gen_uri_delims - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "gen_uri_delims - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "gen_uri_delims - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "gen_uri_delims - Win32 Release"
-
-OUTDIR=.
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\gen_uri_delims.exe"
-
-!ELSE
-
-ALL : "$(OUTDIR)\gen_uri_delims.exe"
-
-!ENDIF
-
-CLEAN :
- -@erase "$(INTDIR)\gen_uri_delims.idb"
- -@erase "$(INTDIR)\gen_uri_delims.obj"
- -@erase "$(OUTDIR)\gen_uri_delims.exe"
-
-"$(INTDIR)" :
- if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS"\
- /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\gen_uri_delims" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:console /incremental:no\
- /pdb:"$(OUTDIR)\Release\gen_uri_delims.pdb" /machine:I386\
- /out:"$(OUTDIR)\gen_uri_delims.exe"
-LINK32_OBJS= \
- "$(INTDIR)\gen_uri_delims.obj"
-
-"$(OUTDIR)\gen_uri_delims.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "gen_uri_delims - Win32 Debug"
-
-OUTDIR=.
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\gen_uri_delims.exe"
-
-!ELSE
-
-ALL : "$(OUTDIR)\gen_uri_delims.exe"
-
-!ENDIF
-
-CLEAN :
- -@erase "$(INTDIR)\gen_uri_delims.idb"
- -@erase "$(INTDIR)\gen_uri_delims.obj"
- -@erase "$(OUTDIR)\Debug\gen_uri_delims.pdb"
- -@erase "$(OUTDIR)\gen_uri_delims.exe"
-
-"$(INTDIR)" :
- if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D\
- "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\gen_uri_delims" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:console /incremental:no\
- /pdb:"$(OUTDIR)\Debug\gen_uri_delims.pdb" /debug /machine:I386\
- /out:"$(OUTDIR)\gen_uri_delims.exe"
-LINK32_OBJS= \
- "$(INTDIR)\gen_uri_delims.obj"
-
-"$(OUTDIR)\gen_uri_delims.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "gen_uri_delims - Win32 Release" || "$(CFG)" ==\
- "gen_uri_delims - Win32 Debug"
-SOURCE=.\gen_uri_delims.c
-
-"$(INTDIR)\gen_uri_delims.obj" : $(SOURCE) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/server/listen.c b/server/listen.c
deleted file mode 100644
index a525de09ba..0000000000
--- a/server/listen.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_network_io.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "ap_listen.h"
-#include "http_log.h"
-#include "mpm.h"
-#include "mpm_common.h"
-
-
-ap_listen_rec *ap_listeners;
-#if APR_HAVE_IPV6
-static int default_family = APR_UNSPEC;
-#else
-static int default_family = APR_INET;
-#endif
-static ap_listen_rec *old_listeners;
-static int ap_listenbacklog;
-static int send_buffer_size;
-
-/* TODO: make_sock is just begging and screaming for APR abstraction */
-static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
-{
- apr_socket_t *s = server->sd;
- int one = 1;
- apr_status_t stat;
-
- stat = apr_setsocketopt(s, APR_SO_REUSEADDR, one);
- if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
- ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
- "make_sock: for address %pI, setsockopt: (SO_REUSEADDR)",
- server->bind_addr);
- apr_socket_close(s);
- return stat;
- }
-
- stat = apr_setsocketopt(s, APR_SO_KEEPALIVE, one);
- if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
- ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
- "make_sock: for address %pI, setsockopt: (SO_KEEPALIVE)",
- server->bind_addr);
- apr_socket_close(s);
- return stat;
- }
-
- /*
- * To send data over high bandwidth-delay connections at full
- * speed we must force the TCP window to open wide enough to keep the
- * pipe full. The default window size on many systems
- * is only 4kB. Cross-country WAN connections of 100ms
- * at 1Mb/s are not impossible for well connected sites.
- * If we assume 100ms cross-country latency,
- * a 4kB buffer limits throughput to 40kB/s.
- *
- * To avoid this problem I've added the SendBufferSize directive
- * to allow the web master to configure send buffer size.
- *
- * The trade-off of larger buffers is that more kernel memory
- * is consumed. YMMV, know your customers and your network!
- *
- * -John Heidemann <johnh@isi.edu> 25-Oct-96
- *
- * If no size is specified, use the kernel default.
- */
- if (send_buffer_size) {
- stat = apr_setsocketopt(s, APR_SO_SNDBUF, send_buffer_size);
- if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
- ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
- "make_sock: failed to set SendBufferSize for "
- "address %pI, using default",
- server->bind_addr);
- /* not a fatal error */
- }
- }
-
-#if APR_TCP_NODELAY_INHERITED
- ap_sock_disable_nagle(s);
-#endif
-
- if ((stat = apr_bind(s, server->bind_addr)) != APR_SUCCESS) {
- ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
- "make_sock: could not bind to address %pI",
- server->bind_addr);
- apr_socket_close(s);
- return stat;
- }
-
- if ((stat = apr_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
- ap_log_perror(APLOG_MARK, APLOG_ERR, stat, p,
- "make_sock: unable to listen for connections on address %pI",
- server->bind_addr);
- apr_socket_close(s);
- return stat;
- }
-
-#ifdef APR_HAS_SO_ACCEPTFILTER
-#ifndef ACCEPT_FILTER_NAME
-#define ACCEPT_FILTER_NAME "dataready"
-#endif
- apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, "");
-#endif
-
- server->sd = s;
- server->active = 1;
- return APR_SUCCESS;
-}
-
-static apr_status_t close_listeners_on_exec(void *v)
-{
- ap_listen_rec *lr;
-
- for (lr = ap_listeners; lr; lr = lr->next) {
- apr_socket_close(lr->sd);
- lr->active = 0;
- }
- return APR_SUCCESS;
-}
-
-
-static void find_default_family(apr_pool_t *p)
-{
-#if APR_HAVE_IPV6
- /* We know the platform supports IPv6, but this particular
- * system may not have IPv6 enabled. See if we can get an
- * AF_INET6 socket.
- */
- if (default_family == APR_UNSPEC) {
- apr_socket_t *tmp_sock;
-
- if (apr_socket_create(&tmp_sock, APR_INET6, SOCK_STREAM,
- p) == APR_SUCCESS) {
- apr_socket_close(tmp_sock);
- default_family = APR_INET6;
- }
- else {
- default_family = APR_INET;
- }
- }
-#endif
-}
-
-
-static void alloc_listener(process_rec *process, char *addr, apr_port_t port)
-{
- ap_listen_rec **walk;
- ap_listen_rec *new;
- apr_status_t status;
- char *oldaddr;
- apr_port_t oldport;
- apr_sockaddr_t *sa;
-
- if (!addr) { /* don't bind to specific interface */
- find_default_family(process->pool);
- switch(default_family) {
- case APR_INET:
- addr = "0.0.0.0";
- break;
-#if APR_HAVE_IPV6
- case APR_INET6:
- addr = "::";
- break;
-#endif
- default:
- ap_assert(1 != 1); /* should not occur */
- }
- }
-
- /* see if we've got an old listener for this address:port */
- for (walk = &old_listeners; *walk; walk = &(*walk)->next) {
- sa = (*walk)->bind_addr;
- apr_sockaddr_port_get(&oldport, sa);
- apr_sockaddr_ip_get(&oldaddr, sa);
- if (!strcmp(oldaddr, addr) && port == oldport) {
- /* re-use existing record */
- new = *walk;
- *walk = new->next;
- new->next = ap_listeners;
- ap_listeners = new;
- return;
- }
- }
-
- /* this has to survive restarts */
- new = apr_palloc(process->pool, sizeof(ap_listen_rec));
- new->active = 0;
- if ((status = apr_sockaddr_info_get(&new->bind_addr, addr, APR_UNSPEC, port, 0,
- process->pool)) != APR_SUCCESS) {
- ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
- "alloc_listener: failed to set up sockaddr for %s", addr);
- return;
- }
- if ((status = apr_socket_create(&new->sd, new->bind_addr->sa.sin.sin_family,
- SOCK_STREAM, process->pool)) != APR_SUCCESS) {
- ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
- "alloc_listener: failed to get a socket for %s", addr);
- return;
- }
- new->next = ap_listeners;
- ap_listeners = new;
-}
-
-#if !defined(SPMT_OS2_MPM)
-static
-#endif
-int ap_listen_open(process_rec *process, apr_port_t port)
-{
- apr_pool_t *pconf = process->pconf;
- ap_listen_rec *lr;
- ap_listen_rec *next;
- int num_open;
-
- /* allocate a default listener if necessary */
- if (ap_listeners == NULL) {
- alloc_listener(process, NULL, port ? port : DEFAULT_HTTP_PORT);
- }
-
- num_open = 0;
- for (lr = ap_listeners; lr; lr = lr->next) {
- if (lr->active) {
- ++num_open;
- }
- else {
- if (make_sock(pconf, lr) == APR_SUCCESS) {
- ++num_open;
- lr->active = 1;
- }
- }
- }
-
- /* close the old listeners */
- for (lr = old_listeners; lr; lr = next) {
- apr_socket_close(lr->sd);
- lr->active = 0;
- next = lr->next;
-/* free(lr);*/
- }
- old_listeners = NULL;
-
- apr_pool_cleanup_register(pconf, NULL, apr_pool_cleanup_null, close_listeners_on_exec);
-
- return num_open ? 0 : -1;
-}
-
-int ap_setup_listeners(server_rec *s)
-{
- ap_listen_rec *lr;
- int num_listeners = 0;
- if (ap_listen_open(s->process, s->port)) {
- return 0;
- }
- for (lr = ap_listeners; lr; lr = lr->next) {
- num_listeners++;
- }
- return num_listeners;
-}
-
-void ap_listen_pre_config(void)
-{
- old_listeners = ap_listeners;
- ap_listeners = NULL;
- ap_listenbacklog = DEFAULT_LISTENBACKLOG;
-}
-
-
-const char *ap_set_listener(cmd_parms *cmd, void *dummy, const char *ips)
-{
- char *host, *scope_id;
- apr_port_t port;
- apr_status_t rv;
-
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- rv = apr_parse_addr_port(&host, &scope_id, &port, ips, cmd->pool);
- if (rv != APR_SUCCESS) {
- return "Invalid address or port";
- }
- if (host && !strcmp(host, "*")) {
- host = NULL;
- }
- if (scope_id) {
- /* XXX scope id support is useful with link-local IPv6 addresses */
- return "Scope id is not supported";
- }
- if (!port) {
- return "Port must be specified";
- }
-
- alloc_listener(cmd->server->process, host, port);
-
- return NULL;
-}
-
-const char *ap_set_listenbacklog(cmd_parms *cmd, void *dummy, const char *arg)
-{
- int b;
-
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- b = atoi(arg);
- if (b < 1) {
- return "ListenBacklog must be > 0";
- }
- ap_listenbacklog = b;
- return NULL;
-}
-
-const char *ap_set_send_buffer_size(cmd_parms *cmd, void *dummy, const char *arg)
-{
- int s = atoi(arg);
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (s < 512 && s != 0) {
- return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
- }
- send_buffer_size = s;
- return NULL;
-}
diff --git a/server/log.c b/server/log.c
deleted file mode 100644
index 4ba0b4c6f3..0000000000
--- a/server/log.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_log.c: Dealing with the logs and errors
- *
- * Rob McCool
- *
- */
-
-#include "apr.h"
-#include "apr_general.h" /* for signal stuff */
-#include "apr_strings.h"
-#include "apr_errno.h"
-#include "apr_thread_proc.h"
-#include "apr_lib.h"
-#include "apr_signal.h"
-
-#define APR_WANT_STDIO
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_main.h"
-
-typedef struct {
- char *t_name;
- int t_val;
-} TRANS;
-
-#ifdef HAVE_SYSLOG
-
-static const TRANS facilities[] = {
- {"auth", LOG_AUTH},
-#ifdef LOG_AUTHPRIV
- {"authpriv",LOG_AUTHPRIV},
-#endif
-#ifdef LOG_CRON
- {"cron", LOG_CRON},
-#endif
-#ifdef LOG_DAEMON
- {"daemon", LOG_DAEMON},
-#endif
-#ifdef LOG_FTP
- {"ftp", LOG_FTP},
-#endif
-#ifdef LOG_KERN
- {"kern", LOG_KERN},
-#endif
-#ifdef LOG_LPR
- {"lpr", LOG_LPR},
-#endif
-#ifdef LOG_MAIL
- {"mail", LOG_MAIL},
-#endif
-#ifdef LOG_NEWS
- {"news", LOG_NEWS},
-#endif
-#ifdef LOG_SYSLOG
- {"syslog", LOG_SYSLOG},
-#endif
-#ifdef LOG_USER
- {"user", LOG_USER},
-#endif
-#ifdef LOG_UUCP
- {"uucp", LOG_UUCP},
-#endif
-#ifdef LOG_LOCAL0
- {"local0", LOG_LOCAL0},
-#endif
-#ifdef LOG_LOCAL1
- {"local1", LOG_LOCAL1},
-#endif
-#ifdef LOG_LOCAL2
- {"local2", LOG_LOCAL2},
-#endif
-#ifdef LOG_LOCAL3
- {"local3", LOG_LOCAL3},
-#endif
-#ifdef LOG_LOCAL4
- {"local4", LOG_LOCAL4},
-#endif
-#ifdef LOG_LOCAL5
- {"local5", LOG_LOCAL5},
-#endif
-#ifdef LOG_LOCAL6
- {"local6", LOG_LOCAL6},
-#endif
-#ifdef LOG_LOCAL7
- {"local7", LOG_LOCAL7},
-#endif
- {NULL, -1},
-};
-#endif
-
-static const TRANS priorities[] = {
- {"emerg", APLOG_EMERG},
- {"alert", APLOG_ALERT},
- {"crit", APLOG_CRIT},
- {"error", APLOG_ERR},
- {"warn", APLOG_WARNING},
- {"notice", APLOG_NOTICE},
- {"info", APLOG_INFO},
- {"debug", APLOG_DEBUG},
- {NULL, -1},
-};
-
-static apr_file_t *stderr_log;
-
-AP_DECLARE(void) ap_open_stderr_log(apr_pool_t *p)
-{
- apr_file_open_stderr(&stderr_log, p);
-}
-
-static int log_child(apr_pool_t *p, const char *progname,
- apr_file_t **fpin)
-{
- /* Child process code for 'ErrorLog "|..."';
- * may want a common framework for this, since I expect it will
- * be common for other foo-loggers to want this sort of thing...
- */
- apr_status_t rc;
- apr_procattr_t *procattr;
- apr_proc_t *procnew;
-
-#ifdef SIGHUP
- /* No concept of a child process on Win32 */
- apr_signal(SIGHUP, SIG_IGN);
-#endif /* ndef SIGHUP */
-
- if (((rc = apr_procattr_create(&procattr, p)) == APR_SUCCESS) &&
- ((rc = apr_procattr_io_set(procattr,
- APR_FULL_BLOCK,
- APR_NO_PIPE,
- APR_NO_PIPE)) == APR_SUCCESS)) {
- char **args;
- const char *pname;
-
- apr_tokenize_to_argv(progname, &args, p);
- pname = apr_pstrdup(p, args[0]);
- procnew = (apr_proc_t *) apr_pcalloc(p, sizeof(*procnew));
- rc = apr_proc_create(procnew, pname, (const char * const *)args,
- NULL, procattr, p);
-
- if (rc == APR_SUCCESS) {
- apr_pool_note_subprocess(p, procnew, kill_after_timeout);
- (*fpin) = procnew->in;
- }
- }
-
- return(rc);
-}
-
-static void open_error_log(server_rec *s, apr_pool_t *p)
-{
- const char *fname;
- int rc;
-
- if (*s->error_fname == '|') {
- apr_file_t *dummy = NULL;
-
- /* This starts a new process... */
- rc = log_child (p, s->error_fname+1, &dummy);
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
- "Couldn't start ErrorLog process");
- exit(1);
- }
-
- s->error_log = dummy;
- }
-
-#ifdef HAVE_SYSLOG
- else if (!strncasecmp(s->error_fname, "syslog", 6)) {
- if ((fname = strchr(s->error_fname, ':'))) {
- const TRANS *fac;
-
- fname++;
- for (fac = facilities; fac->t_name; fac++) {
- if (!strcasecmp(fname, fac->t_name)) {
- openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID,
- fac->t_val);
- s->error_log = NULL;
- return;
- }
- }
- }
- else
- openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
-
- s->error_log = NULL;
- }
-#endif
- else {
- fname = ap_server_root_relative(p, s->error_fname);
- rc = apr_file_open(&s->error_log, fname,
- APR_APPEND | APR_READ | APR_WRITE | APR_CREATE,
- APR_OS_DEFAULT, p);
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
- "%s: could not open error log file %s.",
- ap_server_argv0, fname);
- exit(1);
- }
- }
-}
-
-void ap_open_logs(server_rec *s_main, apr_pool_t *p)
-{
- apr_status_t rc = APR_SUCCESS;
- server_rec *virt, *q;
- int replace_stderr;
- apr_file_t *errfile = NULL;
-
- open_error_log(s_main, p);
-
- replace_stderr = 1;
- if (s_main->error_log) {
- /* replace stderr with this new log */
- apr_file_flush(s_main->error_log);
- apr_file_open_stderr(&errfile, p);
- if ((rc = apr_file_dup(&errfile, s_main->error_log, p)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rc, s_main,
- "unable to replace stderr with error_log");
- } else {
- replace_stderr = 0;
- }
- }
- /* note that stderr may still need to be replaced with something
- * because it points to the old error log, or back to the tty
- * of the submitter.
- */
- if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, errno, s_main,
- "unable to replace stderr with /dev/null");
- }
-
- for (virt = s_main->next; virt; virt = virt->next) {
- if (virt->error_fname) {
- for (q=s_main; q != virt; q = q->next)
- if (q->error_fname != NULL &&
- strcmp(q->error_fname, virt->error_fname) == 0)
- break;
- if (q == virt)
- open_error_log(virt, p);
- else
- virt->error_log = q->error_log;
- }
- else
- virt->error_log = s_main->error_log;
- }
-}
-
-AP_DECLARE(void) ap_error_log2stderr(server_rec *s) {
- apr_file_t *errfile = NULL;
-
- apr_file_open_stderr(&errfile, s->process->pool);
- if (s->error_log != NULL) {
- apr_file_dup(&(s->error_log), errfile, s->process->pool);
- }
-}
-
-static void log_error_core(const char *file, int line, int level,
- apr_status_t status, const server_rec *s,
- const request_rec *r, apr_pool_t *pool,
- const char *fmt, va_list args)
-{
- char errstr[MAX_STRING_LEN];
- size_t len;
- apr_file_t *logf = NULL;
- const char *referer;
- int level_and_mask = level & APLOG_LEVELMASK;
-
- if (s == NULL) {
- /*
- * If we are doing stderr logging (startup), don't log messages that are
- * above the default server log level unless it is a startup/shutdown
- * notice
- */
- if ((level_and_mask != APLOG_NOTICE) &&
- (level_and_mask > DEFAULT_LOGLEVEL))
- return;
- logf = stderr_log;
- }
- else if (s->error_log) {
- /*
- * If we are doing normal logging, don't log messages that are
- * above the server log level unless it is a startup/shutdown notice
- */
- if ((level_and_mask != APLOG_NOTICE) &&
- (level_and_mask > s->loglevel))
- return;
- logf = s->error_log;
- }
-#ifdef TPF
- else if (tpf_child) {
- /*
- * If we are doing normal logging, don't log messages that are
- * above the server log level unless it is a startup/shutdown notice
- */
- if ((level_and_mask != APLOG_NOTICE) &&
- (level_and_mask > s->loglevel))
- return;
- logf = stderr;
- }
-#endif /* TPF */
- else {
- /*
- * If we are doing syslog logging, don't log messages that are
- * above the server log level (including a startup/shutdown notice)
- */
- if (level_and_mask > s->loglevel)
- return;
- }
-
- if (logf && ((level & APLOG_STARTUP) != APLOG_STARTUP)) {
- errstr[0] = '[';
- apr_ctime(errstr + 1, apr_time_now());
- errstr[1 + APR_CTIME_LEN - 1] = ']';
- errstr[1 + APR_CTIME_LEN ] = ' ';
- len = 1 + APR_CTIME_LEN + 1;
- } else {
- len = 0;
- }
-
- if ((level & APLOG_STARTUP) != APLOG_STARTUP) {
- len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
- "[%s] ", priorities[level_and_mask].t_name);
- }
-#ifndef TPF
- if (file && level_and_mask == APLOG_DEBUG) {
-#ifdef _OSD_POSIX
- char tmp[256];
- char *e = strrchr(file, '/');
-
- /* In OSD/POSIX, the compiler returns for __FILE__
- * a string like: __FILE__="*POSIX(/usr/include/stdio.h)"
- * (it even returns an absolute path for sources in
- * the current directory). Here we try to strip this
- * down to the basename.
- */
- if (e != NULL && e[1] != '\0') {
- apr_snprintf(tmp, sizeof(tmp), "%s", &e[1]);
- e = &tmp[strlen(tmp)-1];
- if (*e == ')')
- *e = '\0';
- file = tmp;
- }
-#endif /*_OSD_POSIX*/
- len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
- "%s(%d): ", file, line);
- }
-#endif /* TPF */
- if (r && r->connection) {
- /* XXX: TODO: add a method of selecting whether logged client
- * addresses are in dotted quad or resolved form... dotted
- * quad is the most secure, which is why I'm implementing it
- * first. -djg
- */
- len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
- "[client %s] ", r->connection->remote_ip);
- }
- if (!(level & APLOG_NOERRNO)
- && (status != 0)) {
- char buf[120];
- len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
- "(%d)%s: ", status, apr_strerror(status, buf, sizeof(buf)));
- }
- len += apr_vsnprintf(errstr + len, MAX_STRING_LEN - len, fmt, args);
-
- if (r && (referer = apr_table_get(r->headers_in, "Referer"))) {
- len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
- ", referer: %s", referer);
- }
-
- /* NULL if we are logging to syslog */
- if (logf) {
- /* Truncate for the terminator (as apr_snprintf does) */
- if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR))
- len = MAX_STRING_LEN - sizeof(APR_EOL_STR);
- strcpy(errstr + len, APR_EOL_STR);
- apr_file_puts(errstr, logf);
- apr_file_flush(logf);
- }
-#ifdef HAVE_SYSLOG
- else {
- syslog(level_and_mask, "%s", errstr);
- }
-#endif
-}
-
-AP_DECLARE(void) ap_log_error(const char *file, int line, int level,
- apr_status_t status, const server_rec *s,
- const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- log_error_core(file, line, level, status, s, NULL, NULL, fmt, args);
- va_end(args);
-}
-
-AP_DECLARE(void) ap_log_perror(const char *file, int line, int level,
- apr_status_t status, apr_pool_t *p,
- const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- log_error_core(file, line, level, status, NULL, NULL, p, fmt, args);
- va_end(args);
-}
-
-AP_DECLARE(void) ap_log_rerror(const char *file, int line, int level,
- apr_status_t status, const request_rec *r,
- const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- log_error_core(file, line, level, status, r->server, r, NULL, fmt, args);
- /*
- * IF the error level is 'warning' or more severe,
- * AND there isn't already error text associated with this request,
- * THEN make the message text available to ErrorDocument and
- * other error processors. This can be disabled by stuffing
- * something, even an empty string, into the "error-notes" cell
- * before calling this routine.
- */
- va_end(args);
- va_start(args,fmt);
- if (((level & APLOG_LEVELMASK) <= APLOG_WARNING)
- && (apr_table_get(r->notes, "error-notes") == NULL)) {
- apr_table_setn(r->notes, "error-notes",
- ap_escape_html(r->pool, apr_pvsprintf(r->pool, fmt,
- args)));
- }
- va_end(args);
-}
-
-void ap_log_pid(apr_pool_t *p, const char *fname)
-{
- apr_file_t *pid_file = NULL;
- apr_finfo_t finfo;
- static pid_t saved_pid = -1;
- pid_t mypid;
- apr_status_t rv;
-
- if (!fname)
- return;
-
- fname = ap_server_root_relative(p, fname);
- mypid = getpid();
- if (mypid != saved_pid
- && apr_stat(&finfo, fname, APR_FINFO_MTIME, p) == APR_SUCCESS) {
- /* WINCH and HUP call this on each restart.
- * Only warn on first time through for this pid.
- *
- * XXX: Could just write first time through too, although
- * that may screw up scripts written to do something
- * based on the last modification time of the pid file.
- */
- ap_log_perror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, p,
- apr_psprintf(p,
- "pid file %s overwritten -- Unclean shutdown of previous Apache run?",
- fname)
- );
- }
-
- if ((rv = apr_file_open(&pid_file, fname, APR_WRITE | APR_CREATE | APR_TRUNCATE,
- APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD, p)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "could not create %s", fname);
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, NULL,
- "%s: could not log pid to file %s",
- ap_server_argv0, fname);
- exit(1);
- }
- apr_file_printf(pid_file, "%ld" APR_EOL_STR, (long)mypid);
- apr_file_close(pid_file);
- saved_pid = mypid;
-}
-
-AP_DECLARE(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
-{
- char time_str[APR_CTIME_LEN];
-
- apr_ctime(time_str, apr_time_now());
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "[%s] file %s, line %d, assertion \"%s\" failed",
- time_str, szFile, nLine, szExp);
-#ifndef WIN32
- /* unix assert does an abort leading to a core dump */
- abort();
-#else
- exit(1);
-#endif
-}
-
-/* piped log support */
-
-#ifdef AP_HAVE_RELIABLE_PIPED_LOGS
-/* forward declaration */
-static void piped_log_maintenance(int reason, void *data, apr_wait_t status);
-
-static int piped_log_spawn(piped_log *pl)
-{
- int rc;
- apr_procattr_t *procattr;
- apr_proc_t *procnew = NULL;
- apr_status_t status;
-
-#ifdef SIGHUP
- apr_signal(SIGHUP, SIG_IGN);
-#endif
- if (((status = apr_procattr_create(&procattr, pl->p)) != APR_SUCCESS) ||
- ((status = apr_procattr_child_in_set(procattr, ap_piped_log_read_fd(pl),
- ap_piped_log_write_fd(pl))) != APR_SUCCESS)) {
- char buf[120];
- /* Something bad happened, give up and go away. */
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "piped_log_spawn: unable to setup child process '%s': %s",
- pl->program, apr_strerror(status, buf, sizeof(buf)));
- rc = -1;
- }
- else {
- char **args;
- const char *pname;
-
- apr_tokenize_to_argv(pl->program, &args, pl->p);
- pname = apr_pstrdup(pl->p, args[0]);
- procnew = apr_pcalloc(pl->p, sizeof(apr_proc_t));
- rc = apr_proc_create(procnew, pname, (const char * const *) args,
- NULL, procattr, pl->p);
-
- if (rc == APR_SUCCESS) {
- /* pjr - This no longer happens inside the child, */
- /* I am assuming that if apr_proc_create was */
- /* successful that the child is running. */
- RAISE_SIGSTOP(PIPED_LOG_SPAWN);
- pl->pid = procnew;
- ap_piped_log_write_fd(pl) = procnew->in;
- apr_proc_other_child_register(procnew, piped_log_maintenance, pl,
- ap_piped_log_write_fd(pl), pl->p);
- }
- }
-
- return 0;
-}
-
-
-static void piped_log_maintenance(int reason, void *data, apr_wait_t status)
-{
- piped_log *pl = data;
- apr_status_t stats;
-
- switch (reason) {
- case APR_OC_REASON_DEATH:
- pl->pid = NULL;
- apr_proc_other_child_unregister(pl);
- if (pl->program == NULL) {
- /* during a restart */
- break;
- }
- break;
- case APR_OC_REASON_LOST:
- pl->pid = NULL;
- apr_proc_other_child_unregister(pl);
- if (pl->program == NULL) {
- /* during a restart */
- break;
- }
- if ((stats = piped_log_spawn(pl)) != APR_SUCCESS) {
- /* what can we do? This could be the error log we're having
- * problems opening up... */
- char buf[120];
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "piped_log_maintenance: unable to respawn '%s': %s",
- pl->program, apr_strerror(stats, buf, sizeof(buf)));
- }
- break;
-
- case APR_OC_REASON_UNWRITABLE:
- /* We should not kill off the pipe here, since it may only be full.
- * If it really is locked, we should kill it off manually. */
- break;
-
- case APR_OC_REASON_RESTART:
- pl->program = NULL;
- if (pl->pid != NULL) {
- apr_proc_kill(pl->pid, SIGTERM);
- }
- break;
-
- case APR_OC_REASON_UNREGISTER:
- break;
- }
-}
-
-
-static apr_status_t piped_log_cleanup(void *data)
-{
- piped_log *pl = data;
-
- if (pl->pid != NULL) {
- apr_proc_kill(pl->pid, SIGTERM);
- }
- apr_proc_other_child_unregister(pl);
- apr_file_close(ap_piped_log_read_fd(pl));
- apr_file_close(ap_piped_log_write_fd(pl));
- return APR_SUCCESS;
-}
-
-
-static apr_status_t piped_log_cleanup_for_exec(void *data)
-{
- piped_log *pl = data;
-
- apr_file_close(ap_piped_log_read_fd(pl));
- apr_file_close(ap_piped_log_write_fd(pl));
- return APR_SUCCESS;
-}
-
-AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program)
-{
- piped_log *pl;
-
- pl = apr_palloc(p, sizeof (*pl));
- pl->p = p;
- pl->program = apr_pstrdup(p, program);
- pl->pid = NULL;
- if (apr_file_pipe_create(&ap_piped_log_read_fd(pl), &ap_piped_log_write_fd(pl), p) != APR_SUCCESS) {
- return NULL;
- }
- apr_pool_cleanup_register(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec);
- if (piped_log_spawn(pl) == -1) {
- int save_errno = errno;
- apr_pool_cleanup_kill(p, pl, piped_log_cleanup);
- apr_file_close(ap_piped_log_read_fd(pl));
- apr_file_close(ap_piped_log_write_fd(pl));
- errno = save_errno;
- return NULL;
- }
- return pl;
-}
-
-#else /* !AP_HAVE_RELIABLE_PIPED_LOGS */
-
-static apr_status_t piped_log_cleanup(void *data)
-{
- piped_log *pl = data;
-
- apr_file_close(ap_piped_log_write_fd(pl));
- return APR_SUCCESS;
-}
-
-AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program)
-{
- piped_log *pl;
- apr_file_t *dummy = NULL;
- int rc;
-
- rc = log_child(p, program, &dummy);
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
- "Couldn't start piped log process");
- exit (1);
- }
-
- pl = apr_palloc(p, sizeof (*pl));
- pl->p = p;
- ap_piped_log_read_fd(pl) = NULL;
- ap_piped_log_write_fd(pl) = dummy;
- apr_pool_cleanup_register(p, pl, piped_log_cleanup, piped_log_cleanup);
-
- return pl;
-}
-
-#endif
-
-AP_DECLARE(void) ap_close_piped_log(piped_log *pl)
-{
- apr_pool_cleanup_run(pl->p, pl, piped_log_cleanup);
-}
-
diff --git a/server/main.c b/server/main.c
deleted file mode 100644
index ad71b60d2b..0000000000
--- a/server/main.c
+++ /dev/null
@@ -1,464 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_getopt.h"
-#include "apr_general.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STDIO
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h"
-#include "http_vhost.h"
-#include "util_uri.h"
-#include "util_ebcdic.h"
-#include "ap_mpm.h"
-
-/* WARNING: Win32 binds http_main.c dynamically to the server. Please place
- * extern functions and global data in another appropriate module.
- *
- * Most significant main() global data can be found in http_config.c
- */
-
-/* XXX - We should be able to grab the per-MPM settings here too */
-static void show_compile_settings(void)
-{
- printf("Server version: %s\n", ap_get_server_version());
- printf("Server built: %s\n", ap_get_server_built());
- printf("Server's Module Magic Number: %u:%u\n",
- MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
- printf("Server compiled with....\n");
-#ifdef BIG_SECURITY_HOLE
- printf(" -D BIG_SECURITY_HOLE\n");
-#endif
-#ifdef SECURITY_HOLE_PASS_AUTHORIZATION
- printf(" -D SECURITY_HOLE_PASS_AUTHORIZATION\n");
-#endif
-#ifdef APACHE_MPM_DIR
- printf(" -D APACHE_MPM_DIR=\"%s\"\n", APACHE_MPM_DIR);
-#endif
-#ifdef HAVE_SHMGET
- printf(" -D HAVE_SHMGET\n");
-#endif
-#if APR_FILE_BASED_SHM
- printf(" -D APR_FILE_BASED_SHM\n");
-#endif
-#if APR_HAS_MMAP
- printf(" -D APR_HAS_MMAP\n");
-#endif
-#ifdef NO_WRITEV
- printf(" -D NO_WRITEV\n");
-#endif
-#ifdef NO_LINGCLOSE
- printf(" -D NO_LINGCLOSE\n");
-#endif
-#if APR_HAVE_IPV6
- printf(" -D APR_HAVE_IPV6\n");
-#endif
-#if APR_USE_FLOCK_SERIALIZE
- printf(" -D APR_USE_FLOCK_SERIALIZE\n");
-#endif
-#if APR_USE_SYSVSEM_SERIALIZE
- printf(" -D APR_USE_SYSVSEM_SERIALIZE\n");
-#endif
-#if APR_USE_FCNTL_SERIALIZE
- printf(" -D APR_USE_FCNTL_SERIALIZE\n");
-#endif
-#if APR_USE_PROC_PTHREAD_SERIALIZE
- printf(" -D APR_USE_PROC_PTHREAD_SERIALIZE\n");
-#endif
-#if APR_USE_PTHREAD_SERIALIZE
- printf(" -D APR_USE_PTHREAD_SERIALIZE\n");
-#endif
-#if APR_PROCESS_LOCK_IS_GLOBAL
- printf(" -D APR_PROCESS_LOCK_IS_GLOBAL\n");
-#endif
-#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
- printf(" -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT\n");
-#endif
-#if APR_HAS_OTHER_CHILD
- printf(" -D APR_HAS_OTHER_CHILD\n");
-#endif
-#ifdef AP_HAVE_RELIABLE_PIPED_LOGS
- printf(" -D AP_HAVE_RELIABLE_PIPED_LOGS\n");
-#endif
-#ifdef BUFFERED_LOGS
- printf(" -D BUFFERED_LOGS\n");
-#ifdef PIPE_BUF
- printf(" -D PIPE_BUF=%ld\n",(long)PIPE_BUF);
-#endif
-#endif
-#if APR_CHARSET_EBCDIC
- printf(" -D APR_CHARSET_EBCDIC\n");
-#endif
-#ifdef APACHE_XLATE
- printf(" -D APACHE_XLATE\n");
-#endif
-#ifdef NEED_HASHBANG_EMUL
- printf(" -D NEED_HASHBANG_EMUL\n");
-#endif
-#ifdef SHARED_CORE
- printf(" -D SHARED_CORE\n");
-#endif
-
-/* This list displays the compiled in default paths: */
-#ifdef HTTPD_ROOT
- printf(" -D HTTPD_ROOT=\"" HTTPD_ROOT "\"\n");
-#endif
-#ifdef SUEXEC_BIN
- printf(" -D SUEXEC_BIN=\"" SUEXEC_BIN "\"\n");
-#endif
-#if defined(SHARED_CORE) && defined(SHARED_CORE_DIR)
- printf(" -D SHARED_CORE_DIR=\"" SHARED_CORE_DIR "\"\n");
-#endif
-#ifdef DEFAULT_PIDLOG
- printf(" -D DEFAULT_PIDLOG=\"" DEFAULT_PIDLOG "\"\n");
-#endif
-#ifdef DEFAULT_SCOREBOARD
- printf(" -D DEFAULT_SCOREBOARD=\"" DEFAULT_SCOREBOARD "\"\n");
-#endif
-#ifdef DEFAULT_LOCKFILE
- printf(" -D DEFAULT_LOCKFILE=\"" DEFAULT_LOCKFILE "\"\n");
-#endif
-#ifdef DEFAULT_ERRORLOG
- printf(" -D DEFAULT_ERRORLOG=\"" DEFAULT_ERRORLOG "\"\n");
-#endif
-#ifdef TYPES_CONFIG_FILE
- printf(" -D TYPES_CONFIG_FILE=\"" TYPES_CONFIG_FILE "\"\n");
-#endif
-#ifdef SERVER_CONFIG_FILE
- printf(" -D SERVER_CONFIG_FILE=\"" SERVER_CONFIG_FILE "\"\n");
-#endif
-}
-
-static void destroy_and_exit_process(process_rec *process, int process_exit_value)
-{
- apr_pool_destroy(process->pool); /* and destroy all descendent pools */
- apr_terminate();
- exit(process_exit_value);
-}
-
-static process_rec *create_process(int argc, const char * const *argv)
-{
- process_rec *process;
- apr_pool_t *cntx;
- apr_status_t stat;
-
- stat = apr_pool_create(&cntx, NULL);
- if (stat != APR_SUCCESS) {
- /* XXX From the time that we took away the NULL pool->malloc mapping
- * we have been unable to log here without segfaulting.
- */
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
- "apr_pool_create() failed to create "
- "initial context");
- apr_terminate();
- exit(1);
- }
-
- ap_open_stderr_log(cntx);
-
- process = apr_palloc(cntx, sizeof(process_rec));
- process->pool = cntx;
-
- apr_pool_create(&process->pconf, process->pool);
- process->argc = argc;
- process->argv = argv;
- process->short_name = apr_filename_of_pathname(argv[0]);
- return process;
-}
-
-static void usage(process_rec *process)
-{
- const char *bin = process->argv[0];
- char pad[MAX_STRING_LEN];
- unsigned i;
-
- for (i = 0; i < strlen(bin); i++)
- pad[i] = ' ';
- pad[i] = '\0';
-#ifdef SHARED_CORE
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0,NULL , "Usage: %s [-R directory] [-D name] [-d directory] [-f file]", bin);
-#else
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Usage: %s [-D name] [-d directory] [-f file]", bin);
-#endif
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " %s [-C \"directive\"] [-c \"directive\"]", pad);
-#ifdef WIN32
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " %s [-k restart|shutdown|start]", pad);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " %s [-n service_name]", pad);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " %s [-i] [-u]", pad);
-#endif
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " %s [-v] [-V] [-h] [-l] [-L] [-t] [-T]", pad);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Options:");
-#ifdef SHARED_CORE
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -R directory : specify an alternate location for shared object files");
-#endif
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -D name : define a name for use in <IfDefine name> directives");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -d directory : specify an alternate initial ServerRoot");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -f file : specify an alternate ServerConfigFile");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -C \"directive\" : process directive before reading config files");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -c \"directive\" : process directive after reading config files");
-#ifdef WIN32
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -n name : set service name and use its ServerConfigFile");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -k shutdown : tell running Apache to shutdown");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -k restart : tell running Apache to do a graceful restart");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -k start : tell Apache to start");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -i : install an Apache service");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -u : uninstall an Apache service");
-#endif
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -v : show version number");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -V : show compile settings");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -h : list available command line options (this page)");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -l : list compiled in modules");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -L : list available configuration directives");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -t -D DUMP_VHOSTS : show parsed settings (currently only vhost settings)");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -t : run syntax check for config files (with docroot check)");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, " -T : run syntax check for config files (without docroot check)");
- /* TODOC: -X goes away, expect MPMs to use -D options */
- destroy_and_exit_process(process, 1);
-}
-
-int main(int argc, const char * const argv[])
-{
- char c;
- int configtestonly = 0;
- const char *confname = SERVER_CONFIG_FILE;
- const char *def_server_root = HTTPD_ROOT;
- process_rec *process;
- server_rec *server_conf;
- apr_pool_t *pglobal;
- apr_pool_t *pconf;
- apr_pool_t *plog; /* Pool of log streams, reset _after_ each read of conf */
- apr_pool_t *ptemp; /* Pool for temporary config stuff, reset often */
- apr_pool_t *pcommands; /* Pool for -D, -C and -c switches */
- apr_getopt_t *opt;
- module **mod;
- const char *optarg;
-
- apr_initialize();
-
- process = create_process(argc, argv);
- pglobal = process->pool;
- pconf = process->pconf;
- ap_server_argv0 = process->short_name;
-
-#if APR_CHARSET_EBCDIC
- if (ap_init_ebcdic(pglobal) != APR_SUCCESS) {
- destroy_and_exit_process(process, 1);
- }
-#endif
-
- ap_setup_prelinked_modules(process);
-
- apr_pool_create(&pcommands, pglobal);
- ap_server_pre_read_config = apr_array_make(pcommands, 1, sizeof(char *));
- ap_server_post_read_config = apr_array_make(pcommands, 1, sizeof(char *));
- ap_server_config_defines = apr_array_make(pcommands, 1, sizeof(char *));
-
- ap_run_rewrite_args(process);
-
- /* Maintain AP_SERVER_BASEARGS list in http_main.h to allow the MPM
- * to safely pass on our args from its rewrite_args() handler.
- */
- apr_getopt_init(&opt, pcommands, process->argc, process->argv);
-
- while (apr_getopt(opt, AP_SERVER_BASEARGS, &c, &optarg)
- == APR_SUCCESS) {
- char **new;
- switch (c) {
- case 'c':
- new = (char **)apr_array_push(ap_server_post_read_config);
- *new = apr_pstrdup(pcommands, optarg);
- break;
- case 'C':
- new = (char **)apr_array_push(ap_server_pre_read_config);
- *new = apr_pstrdup(pcommands, optarg);
- break;
- case 'd':
- def_server_root = optarg;
- break;
- case 'D':
- new = (char **)apr_array_push(ap_server_config_defines);
- *new = apr_pstrdup(pcommands, optarg);
- break;
- case 'f':
- confname = optarg;
- break;
- case 'v':
- printf("Server version: %s\n", ap_get_server_version());
- printf("Server built: %s\n", ap_get_server_built());
- destroy_and_exit_process(process, 0);
- case 'V':
- show_compile_settings();
- destroy_and_exit_process(process, 0);
- case 'l':
- ap_show_modules();
- destroy_and_exit_process(process, 0);
- case 'L':
- ap_show_directives();
- destroy_and_exit_process(process, 0);
- case 't':
- configtestonly = 1;
- break;
- case '?':
- case 'h':
- usage(process);
- }
- }
-
- apr_pool_create(&plog, pglobal);
- apr_pool_create(&ptemp, pconf);
-
- /* Note that we preflight the config file once
- before reading it _again_ in the main loop.
- This allows things, log files configuration
- for example, to settle down. */
-
- ap_server_root = def_server_root;
- server_conf = ap_read_config(process, ptemp, confname, &ap_conftree);
- ap_run_pre_config(pconf, plog, ptemp);
- ap_process_config_tree(server_conf, ap_conftree, process->pconf, ptemp);
- ap_fixup_virtual_hosts(pconf, server_conf);
- ap_fini_vhost_config(pconf, server_conf);
- apr_sort_hooks();
- if (configtestonly) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Syntax OK\n");
- destroy_and_exit_process(process, 0);
- }
- apr_pool_clear(plog);
- ap_run_open_logs(pconf, plog, ptemp, server_conf);
- ap_run_post_config(pconf, plog, ptemp, server_conf);
- apr_pool_destroy(ptemp);
-
- for (;;) {
- apr_hook_deregister_all();
- apr_pool_clear(pconf);
- for (mod = ap_prelinked_modules; *mod != NULL; mod++) {
- ap_register_hooks(*mod, pconf);
- }
-
-
- /* This is a hack until we finish the code so that it only reads
- * the config file once and just operates on the tree already in
- * memory. rbb
- */
- ap_conftree = NULL;
- apr_pool_create(&ptemp, pconf);
- ap_server_root = def_server_root;
- server_conf = ap_read_config(process, ptemp, confname, &ap_conftree);
- ap_run_pre_config(pconf, plog, ptemp);
- ap_process_config_tree(server_conf, ap_conftree, process->pconf, ptemp);
- ap_fixup_virtual_hosts(pconf, server_conf);
- ap_fini_vhost_config(pconf, server_conf);
- apr_sort_hooks();
- apr_pool_clear(plog);
- ap_run_open_logs(pconf, plog, ptemp, server_conf);
- ap_run_post_config(pconf, plog, ptemp, server_conf);
- apr_pool_destroy(ptemp);
-
- ap_run_optional_fn_retrieve();
-
- if (ap_mpm_run(pconf, plog, server_conf)) break;
- }
- destroy_and_exit_process(process, 0);
- return 0; /* Supress compiler warning. */
-}
-
-/* force Expat to be linked into the server executable */
-#if defined(USE_EXPAT) && !defined(SHARED_CORE_BOOTSTRAP)
-#include "xmlparse.h"
-const XML_LChar *suck_in_expat(void);
-const XML_LChar *suck_in_expat(void)
-{
- return XML_ErrorString(XML_ERROR_NONE);
-}
-#endif /* USE_EXPAT */
-
-#ifndef SHARED_CORE_BOOTSTRAP
-/*
- * Force apr_password_validate() into the image so that modules like
- * mod_auth can use it even if they're dynamically loaded.
- */
-void suck_in_apr_password_validate(void);
-void suck_in_apr_password_validate(void)
-{
- apr_password_validate("a", "b");
-}
-#endif
-
-#ifdef AP_USING_AUTOCONF
-/* This ugly little hack pulls any function referenced in exports.c into
- * the web server. exports.c is generated during the build, and it
- * has all of the APR functions specified by the apr/apr.exports and
- * apr-util/aprutil.exports files.
- */
-const void *suck_in_APR(void);
-const void *suck_in_APR(void)
-{
- extern const void *ap_ugly_hack;
-
- return ap_ugly_hack;
-}
-#endif
diff --git a/server/mpm/.cvsignore b/server/mpm/.cvsignore
deleted file mode 100644
index bd5fe06963..0000000000
--- a/server/mpm/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-.deps
diff --git a/server/mpm/MPM.NAMING b/server/mpm/MPM.NAMING
deleted file mode 100644
index 62b60a0328..0000000000
--- a/server/mpm/MPM.NAMING
+++ /dev/null
@@ -1,13 +0,0 @@
-
-The following MPMs currently exist:
-
- prefork ....... Multi Process Model with Preforking (Apache 1.3)
- perchild ...... Multi Process Model with Threading.
- Constant number of processes, variable number of threads
- each child process can have a different uid/gid.
- threaded ...... Multi Process Model with Threading.
- Variable number of processes, constant number of
- threads/child (= Apache/thread)
- spmt_os2 ...... Single Process Model with Threading on OS/2
- winnt ......... Single Process Model with Threading on Windows NT
-
diff --git a/server/mpm/Makefile.in b/server/mpm/Makefile.in
deleted file mode 100644
index b68fee5cd7..0000000000
--- a/server/mpm/Makefile.in
+++ /dev/null
@@ -1,4 +0,0 @@
-
-SUBDIRS = $(MPM_NAME)
-
-include $(top_srcdir)/build/rules.mk
diff --git a/server/mpm/beos/.cvsignore b/server/mpm/beos/.cvsignore
deleted file mode 100644
index 84df257214..0000000000
--- a/server/mpm/beos/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.deps
-.libs
-*.lo
-*.la
-Makefile
diff --git a/server/mpm/beos/Makefile.in b/server/mpm/beos/Makefile.in
deleted file mode 100644
index 3f88b0415f..0000000000
--- a/server/mpm/beos/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-LTLIBRARY_NAME = libbeos.la
-LTLIBRARY_SOURCES = beos.c
-
-include $(top_srcdir)/build/ltlib.mk
diff --git a/server/mpm/beos/beos.c b/server/mpm/beos/beos.c
deleted file mode 100644
index c0128df9b5..0000000000
--- a/server/mpm/beos/beos.c
+++ /dev/null
@@ -1,1122 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* The new BeOS MPM!
- *
- * This one basically is a single process multi threaded model, but
- * I couldn't be bothered adding the spmt_ to the front of the name!
- * Anyway, this is still under development so it isn't yet the default
- * choice.
- */
-
-#define CORE_PRIVATE
-
-#include "apr_strings.h"
-#include "apr_portable.h"
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h" /* for read_config */
-#include "http_core.h" /* for get_remote_host */
-#include "http_connection.h"
-#include "ap_mpm.h"
-#include "beosd.h"
-#include "ap_listen.h"
-#include "scoreboard.h"
-#include <kernel/OS.h>
-#include "mpm_common.h"
-#include "mpm.h"
-#include <unistd.h>
-#include <sys/socket.h>
-#include <signal.h>
-
-/*
- * Actual definitions of config globals
- */
-
-int ap_threads_per_child=HARD_THREAD_LIMIT; /* Worker threads per child */
-int ap_max_requests_per_child=0;
-static const char *ap_pid_fname=NULL;
-static int ap_threads_to_start=0;
-static int min_spare_threads=0;
-static int max_spare_threads=0;
-static int ap_thread_limit=0;
-static int num_listening_sockets = 0; /* set by open_listeners in ap_mpm_run */
-static apr_socket_t ** listening_sockets;
-apr_lock_t *accept_mutex = NULL;
-
-static apr_pool_t *pconf; /* Pool for config stuff */
-static apr_pool_t *pchild; /* Pool for httpd child stuff */
-
-static int server_pid;
-
-/* Keep track of the number of worker threads currently active */
-static int worker_thread_count;
-apr_lock_t *worker_thread_count_mutex;
-
-/* The structure used to pass unique initialization info to each thread */
-typedef struct {
- int slot;
- apr_pool_t *tpool;
-} proc_info;
-
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across SIGWINCH restarts. We use this
- * value to optimize routines that have to scan the entire scoreboard.
- */
-int ap_max_child_assigned = -1;
-int ap_max_threads_limit = -1;
-char ap_coredump_dir[MAX_STRING_LEN];
-
-static apr_socket_t *udp_sock;
-static apr_sockaddr_t *udp_sa;
-
-/* shared http_main globals... */
-
-server_rec *ap_server_conf;
-
-/* one_process */
-static int one_process = 0;
-
-#ifdef DEBUG_SIGSTOP
-int raise_sigstop_flags;
-#endif
-
-/* a clean exit from a child with proper cleanup
- static void clean_child_exit(int code) __attribute__ ((noreturn)); */
-static void clean_child_exit(int code)
-{
- if (pchild)
- apr_pool_destroy(pchild);
- exit(code);
-}
-
-/* handle all varieties of core dumping signals */
-static void sig_coredump(int sig)
-{
- chdir(ap_coredump_dir);
- signal(sig, SIG_DFL);
- kill(server_pid, sig);
- /* At this point we've got sig blocked, because we're still inside
- * the signal handler. When we leave the signal handler it will
- * be unblocked, and we'll take the signal... and coredump or whatever
- * is appropriate for this particular Unix. In addition the parent
- * will see the real signal we received -- whereas if we called
- * abort() here, the parent would only see SIGABRT.
- */
-}
-
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-ap_generation_t volatile ap_my_generation = 0;
-
-/*
- * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
- * functions to initiate shutdown or restart without relying on signals.
- * Previously this was initiated in sig_term() and restart() signal handlers,
- * but we want to be able to start a shutdown/restart from other sources --
- * e.g. on Win32, from the service manager. Now the service manager can
- * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
- * these functions can also be called by the child processes, since global
- * variables are no longer used to pass on the required action to the parent.
- *
- * These should only be called from the parent process itself, since the
- * parent process will use the shutdown_pending and restart_pending variables
- * to determine whether to shutdown or restart. The child process should
- * call signal_parent() directly to tell the parent to die -- this will
- * cause neither of those variable to be set, which the parent will
- * assume means something serious is wrong (which it will be, for the
- * child to force an exit) and so do an exit anyway.
- */
-
-static void ap_start_shutdown(void)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-/* do a graceful restart if graceful == 1 */
-static void ap_start_restart(int graceful)
-{
-
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- is_graceful = graceful;
- if (is_graceful){
- apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
- }
-}
-
-static void sig_term(int sig)
-{
- ap_start_shutdown();
-}
-
-static void restart(int sig)
-{
- ap_start_restart(sig == SIGWINCH);
-}
-
-static void tell_workers_to_exit(void)
-{
- apr_size_t len;
- int i = 0;
- for (i = 0 ; i < ap_max_child_assigned; i++){
- len = 4;
- if (apr_sendto(udp_sock, udp_sa, 0, "die!", &len) != APR_SUCCESS)
- break;
- }
-}
-
-static void set_signals(void)
-{
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
- if (!one_process) {
- sa.sa_handler = sig_coredump;
-
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
- if (sigaction(SIGBUS, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
- if (sigaction(SIGABRT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
- if (sigaction(SIGILL, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
- sa.sa_flags = 0;
- }
- sa.sa_handler = sig_term;
- if (sigaction(SIGTERM, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
- if (sigaction(SIGINT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
-
- sa.sa_handler = SIG_IGN;
- if (sigaction(SIGPIPE, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
-
- /* we want to ignore HUPs and WINCH while we're busy processing one */
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sa.sa_handler = restart;
- if (sigaction(SIGHUP, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
- if (sigaction(SIGWINCH, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
-}
-
-/*****************************************************************
- * Here follows a long bunch of generic server bookkeeping stuff...
- */
-
-int ap_graceful_stop_signalled(void)
-{
- /* XXX - Does this really work? - Manoj */
- return is_graceful;
-}
-
-/*****************************************************************
- * Child process main loop.
- */
-
-static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num)
-{
- conn_rec *current_conn;
- long conn_id = my_child_num;
- int csd;
-
- (void)apr_os_sock_get(&csd, sock);
-
- if (csd >= FD_SETSIZE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
- "filedescriptor (%u) larger than FD_SETSIZE (%u) "
- "found, you probably need to rebuild Apache with a "
- "larger FD_SETSIZE", csd, FD_SETSIZE);
- apr_socket_close(sock);
- return;
- }
-
- current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id);
-
- if (current_conn) {
- ap_process_connection(current_conn);
- ap_lingering_close(current_conn);
- }
-}
-
-static int32 worker_thread(void * dummy)
-{
- proc_info * ti = dummy;
- int child_slot = ti->slot;
- apr_pool_t *tpool = ti->tpool;
- apr_socket_t *csd = NULL;
- apr_pool_t *ptrans; /* Pool for per-transaction stuff */
- apr_socket_t *sd = NULL;
- apr_status_t rv = APR_EINIT;
- int srv , n;
- int curr_pollfd = 0, last_pollfd = 0;
- sigset_t sig_mask;
- int requests_this_child = ap_max_requests_per_child;
- apr_pollfd_t *pollset;
- /* each worker thread is in control of it's own destiny...*/
- int this_worker_should_exit = 0;
- free(ti);
-
- /* block the signals for this thread */
- sigfillset(&sig_mask);
- sigprocmask(SIG_BLOCK, &sig_mask, NULL);
-
- apr_pool_create(&ptrans, tpool);
-
- apr_lock_acquire(worker_thread_count_mutex);
- worker_thread_count++;
- apr_lock_release(worker_thread_count_mutex);
-
- (void) ap_update_child_status(0, child_slot, SERVER_STARTING,
- (request_rec*)NULL);
-
- apr_poll_setup(&pollset, num_listening_sockets, tpool);
- for(n=0 ; n <= num_listening_sockets ; n++)
- apr_poll_socket_add(pollset, listening_sockets[n], APR_POLLIN);
-
- while (1) {
- /* If we're here, then chances are (unless we're the first thread created) we're going
- to be held up on the accept_muetx, so doing this here shouldn't be a peformance hit.
- If it is, you probably need more threads...
- */
-
- this_worker_should_exit |= (ap_max_requests_per_child != 0) && (requests_this_child <= 0);
-
- if (this_worker_should_exit) break;
-
- (void) ap_update_child_status(0, child_slot, SERVER_READY,
- (request_rec*)NULL);
-
- apr_lock_acquire(accept_mutex);
-
- while (!this_worker_should_exit) {
- apr_int16_t event;
- apr_status_t ret;
-
- ret = apr_poll(pollset, &srv, -1);
-
- if (ret != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(ret)) {
- continue;
- }
- /* poll() will only return errors in catastrophic
- * circumstances. Let's try exiting gracefully, for now. */
- ap_log_error(APLOG_MARK, APLOG_ERR, ret, (const server_rec *)
- ap_server_conf, "apr_poll: (listen)");
- this_worker_should_exit = 1;
- } else {
- /* if we've bailed in apr_poll what's the point of trying to use the data? */
- apr_poll_revents_get(&event, listening_sockets[0], pollset);
-
- if (event & APR_POLLIN){
- apr_sockaddr_t *rec_sa;
- char *tmpbuf = apr_pcalloc(ptrans, sizeof(char) * 5);
- apr_size_t len = 5;
- apr_sockaddr_info_get(&rec_sa, "127.0.0.1", APR_UNSPEC, 7772, 0, ptrans);
-
- if ((ret = apr_recvfrom(rec_sa, listening_sockets[0], 0, tmpbuf, &len))
- != APR_SUCCESS){
- ap_log_error(APLOG_MARK, APLOG_ERR, ret, NULL,
- "error getting data from UDP!!");
- }else {
- /* add checking??? */
- }
- this_worker_should_exit = 1;
- }
- }
-
- if (this_worker_should_exit) break;
-
- if (num_listening_sockets == 1) {
- sd = ap_listeners->sd;
- goto got_fd;
- }
- else {
- /* find a listener */
- curr_pollfd = last_pollfd;
- do {
- curr_pollfd++;
-
- if (curr_pollfd > num_listening_sockets)
- curr_pollfd = 1;
-
- /* Get the revent... */
- apr_poll_revents_get(&event, listening_sockets[curr_pollfd], pollset);
-
- if (event & APR_POLLIN) {
- last_pollfd = curr_pollfd;
- sd = listening_sockets[curr_pollfd];
- goto got_fd;
- }
- } while (curr_pollfd != last_pollfd);
- }
- }
- got_fd:
-
- if (!this_worker_should_exit) {
- rv = apr_accept(&csd, sd, ptrans);
- apr_lock_release(accept_mutex);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
- "apr_accept");
- } else {
- process_socket(ptrans, csd, child_slot);
- requests_this_child--;
- }
- }
- else {
- apr_lock_release(accept_mutex);
- break;
- }
- apr_pool_clear(ptrans);
-
- }
-
- ap_update_child_status(0, child_slot, SERVER_DEAD, (request_rec*)NULL);
-
- apr_lock_acquire(worker_thread_count_mutex);
- worker_thread_count--;
- apr_lock_release(worker_thread_count_mutex);
-
- return (0);
-}
-
-static int make_worker(server_rec *s, int slot)
-{
- thread_id tid;
- proc_info *my_info = (proc_info *)malloc(sizeof(proc_info)); /* freed by thread... */
-
- if (my_info == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
- "malloc: out of memory");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- my_info->slot = slot;
- apr_pool_create(&my_info->tpool, pchild);
-
- if (slot + 1 > ap_max_child_assigned)
- ap_max_child_assigned = slot + 1;
-
- if (one_process) {
- set_signals();
- ap_scoreboard_image->parent[0].pid = getpid();
- return 0;
- }
-
- (void) ap_update_child_status(0, slot, SERVER_STARTING, (request_rec*)NULL);
- tid = spawn_thread(worker_thread, "apache_worker", B_NORMAL_PRIORITY,
- my_info);
- if (tid < B_NO_ERROR) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
- "spawn_thread: Unable to start a new thread");
- /* In case system resources are maxxed out, we don't want
- * Apache running away with the CPU trying to fork over and
- * over and over again. */
- (void) ap_update_child_status(0, slot, SERVER_DEAD,
- (request_rec*)NULL);
-
- sleep(10);
- free(my_info);
-
- return -1;
- }
- resume_thread(tid);
-
- ap_scoreboard_image->servers[0][slot].tid = tid;
- return 0;
-}
-
-/* start up a bunch of children */
-static void startup_threads(int number_to_start)
-{
- int i;
-
- for (i = 0; number_to_start && i < ap_thread_limit; ++i) {
- if (ap_scoreboard_image->servers[0][i].tid) {
- continue;
- }
- if (make_worker(ap_server_conf, i) < 0) {
- break;
- }
- --number_to_start;
- }
-}
-
-
-/*
- * spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
-static void perform_idle_server_maintenance(void)
-{
- int i;
- int free_length;
- int free_slots[MAX_SPAWN_RATE];
- int last_non_dead;
-
- /* initialize the free_list */
- free_length = 0;
-
- for (i = 0; i < ap_thread_limit; ++i) {
- if (ap_scoreboard_image->servers[0][i].tid == 0) {
- if (free_length < spawn_rate) {
- free_slots[free_length] = i;
- ++free_length;
- }
- }
- else {
- last_non_dead = i;
- }
-
- if (i >= ap_max_child_assigned && free_length >= spawn_rate) {
- break;
- }
- }
- ap_max_child_assigned = last_non_dead + 1;
-
- if (free_length > 0) {
- for (i = 0; i < free_length; ++i) {
- make_worker(ap_server_conf, free_slots[i]);
- }
- /* the next time around we want to spawn twice as many if this
- * wasn't good enough, but not if we've just done a graceful
- */
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
- } else if (spawn_rate < MAX_SPAWN_RATE) {
- spawn_rate *= 2;
- }
- } else {
- spawn_rate = 1;
- }
-}
-
-static void server_main_loop(int remaining_threads_to_start)
-{
- int child_slot;
- apr_wait_t status;
- apr_proc_t pid;
- int i;
-
- while (!restart_pending && !shutdown_pending) {
- ap_wait_or_timeout(&status, &pid, pconf);
-
- if (pid.pid >= 0) {
- ap_process_child_status(&pid, status);
- /* non-fatal death... note that it's gone in the scoreboard. */
- child_slot = -1;
- for (i = 0; i < ap_max_child_assigned; ++i) {
- if (ap_scoreboard_image->servers[0][i].tid == pid.pid) {
- child_slot = i;
- break;
- }
- }
- if (child_slot >= 0) {
- ap_scoreboard_image->servers[0][child_slot].tid = 0;
- (void) ap_update_child_status(0, child_slot, SERVER_DEAD, (request_rec*)NULL);
-
- if (remaining_threads_to_start
- && child_slot < ap_thread_limit) {
- /* we're still doing a 1-for-1 replacement of dead
- * children with new children
- */
- make_worker(ap_server_conf, child_slot);
- --remaining_threads_to_start;
- }
-#if APR_HAS_OTHER_CHILD
- }
- else if (apr_proc_other_child_read(&pid, status) == 0) {
- /* handled */
-#endif
- }
- else if (is_graceful) {
- /* Great, we've probably just lost a slot in the
- * scoreboard. Somehow we don't know about this
- * child.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf,
- "long lost child came home! (pid %ld)", pid.pid);
- }
-
- /* Don't perform idle maintenance when a child dies,
- * only do it when there's a timeout. Remember only a
- * finite number of children can die, and it's pretty
- * pathological for a lot to die suddenly.
- */
- continue;
- }
- else if (remaining_threads_to_start) {
- /* we hit a 1 second timeout in which none of the previous
- * generation of children needed to be reaped... so assume
- * they're all done, and pick up the slack if any is left.
- */
- startup_threads(remaining_threads_to_start);
- remaining_threads_to_start = 0;
- /* In any event we really shouldn't do the code below because
- * few of the servers we just started are in the IDLE state
- * yet, so we'd mistakenly create an extra server.
- */
- continue;
- }
- perform_idle_server_maintenance();
- }
-}
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = ap_max_child_assigned;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_DYNAMIC;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_NOT_SUPPORTED;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = ap_threads_per_child;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
-{
- int remaining_threads_to_start, i,j;
- apr_status_t rv;
- ap_listen_rec *lr;
- pconf = _pconf;
- ap_server_conf = s;
-
- ap_scoreboard_fname = DEFAULT_SCOREBOARD;
-
- /* BeOS R5 doesn't support pipes on select() calls, so we use a
- UDP socket as these are supported in both R5 and BONE. If we only cared
- about BONE we'd use a pipe, but there it is.
- As we have UDP support in APR, now use the APR functions and check all the
- return values...
- */
- if (apr_sockaddr_info_get(&udp_sa, "127.0.0.1", APR_UNSPEC, 7772, 0, _pconf)
- != APR_SUCCESS){
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, s,
- "couldn't create control socket information, shutting down");
- return 1;
- }
- if (apr_socket_create(&udp_sock, udp_sa->sa.sin.sin_family, SOCK_DGRAM,
- _pconf) != APR_SUCCESS){
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, s,
- "couldn't create control socket, shutting down");
- return 1;
- }
- if (apr_bind(udp_sock, udp_sa) != APR_SUCCESS){
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, s,
- "couldn't bind UDP socket!");
- return 1;
- }
-
- if ((num_listening_sockets = ap_setup_listeners(ap_server_conf)) < 1) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
- "no listening sockets available, shutting down");
- return 1;
- }
-
- ap_log_pid(pconf, ap_pid_fname);
-
- /*
- * Create our locks...
- */
-
- /* accept_mutex
- * used to lock around select so we only have one thread
- * in select at a time
- */
- if ((rv = apr_lock_create(&accept_mutex, APR_MUTEX, APR_CROSS_PROCESS,
- NULL, pconf)) != APR_SUCCESS) {
- /* tsch tsch, can't have more than one thread in the accept loop
- at a time so we need to fall on our sword... */
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
- "Couldn't create accept lock");
- return 1;
- }
-
- /* worker_thread_count_mutex
- * locks the worker_thread_count so we have ana ccurate count...
- */
- if ((rv = apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_CROSS_PROCESS,
- NULL, pconf)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
- "Couldn't create worker thread count lock");
- return 1;
- }
-
- /*
- * Startup/shutdown...
- */
-
- if (!is_graceful)
- ap_create_scoreboard(pconf, SB_SHARED);
-
- if (!is_graceful) {
- for (i = 0; i < HARD_SERVER_LIMIT; i++) {
- ap_scoreboard_image->parent[i].pid = 0;
- for (j = 0;j < HARD_THREAD_LIMIT; j++)
- ap_scoreboard_image->servers[i][j].tid = 0;
- }
- }
- if (HARD_SERVER_LIMIT == 1)
- ap_scoreboard_image->parent[0].pid = getpid();
-
- set_signals();
-
- /* Sanity checks to avoid thrashing... */
- if (max_spare_threads < min_spare_threads )
- max_spare_threads = min_spare_threads;
-
- /* If we're doing a graceful_restart then we're going to see a lot
- * of threads exiting immediately when we get into the main loop
- * below (because we just sent them SIGWINCH). This happens pretty
- * rapidly... and for each one that exits we'll start a new one until
- * we reach at least threads_min_free. But we may be permitted to
- * start more than that, so we'll just keep track of how many we're
- * supposed to start up without the 1 second penalty between each fork.
- */
- remaining_threads_to_start = ap_threads_to_start;
- /* sanity check on the number to start... */
- if (remaining_threads_to_start > ap_thread_limit) {
- remaining_threads_to_start = ap_thread_limit;
- }
-
- /* setup the child pool to use for the workers. Each worker creates
- * a seperate pool of it's own to use.
- */
- apr_pool_create(&pchild, pconf);
- ap_run_child_init(pchild, ap_server_conf);
-
- /* Now that we have the child pool (pchild) we can allocate
- * the listenfds and creat the pollset...
- */
- listening_sockets = apr_palloc(pchild,
- sizeof(*listening_sockets) * (num_listening_sockets + 1));
-
- listening_sockets[0] = udp_sock;
- for (lr = ap_listeners, i = 1; i <= num_listening_sockets; lr = lr->next, ++i)
- listening_sockets[i]=lr->sd;
-
- /* we assume all goes OK...hmm might want to check that! */
- if (!is_graceful) {
- startup_threads(remaining_threads_to_start);
- remaining_threads_to_start = 0;
- }
- else {
- /* give the system some time to recover before kicking into
- * exponential mode */
- hold_off_on_exponential_spawning = 10;
- }
-
- /*
- * record that we've entered the world !
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "%s configured -- resuming normal operations",
- ap_get_server_version());
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "Server built: %s", ap_get_server_built());
-
- restart_pending = shutdown_pending = 0;
-
- /*
- * main_loop until it's all over
- */
- server_main_loop(remaining_threads_to_start);
-
- tell_workers_to_exit(); /* if we get here we're exiting... */
- sleep(1); /* give them a brief chance to exit */
-
- /* close the UDP socket we've been using... */
- apr_socket_close(listening_sockets[0]);
-
- /*
- * If we get here we're shutting down...
- */
- if (shutdown_pending) {
- /* Time to gracefully shut down:
- * Kill child processes, tell them to call child_exit, etc...
- */
- if (beosd_killpg(getpgrp(), SIGTERM) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
- "killpg SIGTERM");
-
- /* cleanup pid file on normal shutdown */
- {
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
- 0, ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
- }
-
- /* use ap_reclaim_child_processes starting with SIGTERM */
- ap_reclaim_child_processes(1);
-
- /* record the shutdown in the log */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "caught SIGTERM, shutting down");
-
- return 1;
- }
-
- /* we've been told to restart */
- signal(SIGHUP, SIG_IGN);
-
- if (one_process) {
- return 1;
- }
-
- if (is_graceful) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGWINCH received. Doing graceful restart");
- }
- else {
- /* Kill 'em all. Since the child acts the same on the parents SIGTERM
- * and a SIGHUP, we may as well use the same signal, because some user
- * pthreads are stealing signals from us left and right.
- */
-
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGHUP received. Attempting to restart");
- }
-
- /* just before we go, tidy up the locks we've created to prevent a
- * potential leak of semaphores... */
- apr_lock_destroy(worker_thread_count_mutex);
- apr_lock_destroy(accept_mutex);
-
- return 0;
-}
-
-static void beos_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- static int restart_num = 0;
- int no_detach = 0;
-
- one_process = !!ap_exists_config_define("ONE_PROCESS");
- no_detach = !!ap_exists_config_define("NO_DETACH");
-
- /* sigh, want this only the second time around */
- if (restart_num++ == 1) {
- is_graceful = 0;
-
- if (!one_process && !no_detach)
- apr_proc_detach();
-
- server_pid = getpid();
- }
-
- beosd_pre_config();
- ap_listen_pre_config();
- ap_threads_to_start = DEFAULT_START_THREADS;
- min_spare_threads = DEFAULT_MIN_FREE_THREADS;
- max_spare_threads = DEFAULT_MAX_FREE_THREADS;
- ap_thread_limit = HARD_THREAD_LIMIT;
- ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_scoreboard_fname = DEFAULT_SCOREBOARD;
- ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-}
-
-static void beos_hooks(apr_pool_t *p)
-{
- one_process = 0;
-
- ap_hook_pre_config(beos_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in <VirtualHost>";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_scoreboard_fname = arg;
- return NULL;
-}
-
-static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_threads_to_start = atoi(arg);
- return NULL;
-}
-
-static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- min_spare_threads = atoi(arg);
- if (min_spare_threads <= 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set to non-positive.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Resetting to 1 to avoid almost certain Apache failure.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Please read the documentation.");
- min_spare_threads = 1;
- }
-
- return NULL;
-}
-
-static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_spare_threads = atoi(arg);
- return NULL;
-}
-
-static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_thread_limit = atoi(arg);
- if (ap_thread_limit > HARD_SERVER_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: MaxClients of %d exceeds compile time limit "
- "of %d servers,", ap_thread_limit, HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering MaxClients to %d. To increase, please "
- "see the", HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_SERVER_LIMIT define in src/include/httpd.h.");
- ap_thread_limit = HARD_SERVER_LIMIT;
- }
- else if (ap_thread_limit < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require MaxClients > 0, setting to 1");
- ap_thread_limit = 1;
- }
- return NULL;
-}
-
-static const char *set_threads_per_child (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_threads_per_child = atoi(arg);
- if (ap_threads_per_child > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: ThreadsPerChild of %d exceeds compile time"
- "limit of %d threads,", ap_threads_per_child,
- HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering ThreadsPerChild to %d. To increase, please"
- "see the", HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_THREAD_LIMIT define in %s", AP_MPM_HARD_LIMITS_FILE);
- }
- else if (ap_threads_per_child < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require ThreadsPerChild > 0, setting to 1");
- ap_threads_per_child = 1;
- }
- return NULL;
-}
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_max_requests_per_child = atoi(arg);
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-static const command_rec beos_cmds[] = {
-LISTEN_COMMANDS
-AP_INIT_TAKE1( "PidFile", set_pidfile, NULL, RSRC_CONF,
- "A file for logging the server process ID"),
-AP_INIT_TAKE1( "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
- "A file for Apache to maintain runtime process management information"),
-AP_INIT_TAKE1( "StartServers", set_daemons_to_start, NULL, RSRC_CONF,
- "Number of child processes launched at server startup"),
-AP_INIT_TAKE1( "MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
- "Minimum number of idle children, to handle request spikes"),
-AP_INIT_TAKE1( "MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
- "Maximum number of idle children" ),
-AP_INIT_TAKE1( "MaxClients", set_server_limit, NULL, RSRC_CONF,
- "Maximum number of children alive at the same time" ),
-AP_INIT_TAKE1( "ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
- "Number of threads each child creates" ),
-AP_INIT_TAKE1( "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
- "Maximum number of requests a particular child serves before dying." ),
-AP_INIT_TAKE1( "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
- "The location of the directory Apache changes to before dumping core" ),
-{ NULL }
-};
-
-module AP_MODULE_DECLARE_DATA mpm_beos_module = {
- MPM20_MODULE_STUFF,
- NULL, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- beos_cmds, /* command apr_table_t */
- beos_hooks /* register_hooks */
-};
-
diff --git a/server/mpm/beos/beos.h b/server/mpm/beos/beos.h
deleted file mode 100644
index 4b37a65ec9..0000000000
--- a/server/mpm/beos/beos.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_BEOS_H
-#define APACHE_MPM_BEOS_H
-
-extern int ap_threads_per_child;
-extern int ap_max_requests_per_child;
-extern int ap_pipe_of_death[2];
-extern int ap_extended_status;
-extern void clean_child_exit(int);
-extern int max_daemons_limit;
-
-#endif /* APACHE_MPM_BEOS_H */
diff --git a/server/mpm/beos/config5.m4 b/server/mpm/beos/config5.m4
deleted file mode 100644
index 4f201408d6..0000000000
--- a/server/mpm/beos/config5.m4
+++ /dev/null
@@ -1,7 +0,0 @@
-dnl ## XXX - Need a more thorough check of the proper flags to use
-
-if test "$MPM_NAME" = "beos" ; then
- apache_apr_flags="--enable-threads"
-
- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
-fi
diff --git a/server/mpm/beos/mpm.h b/server/mpm/beos/mpm.h
deleted file mode 100644
index 3a652f0502..0000000000
--- a/server/mpm/beos/mpm.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_BEOS_H
-#define APACHE_MPM_BEOS_H
-
-#define BEOS_MPM
-#include "scoreboard.h"
-
-#define MPM_NAME "Beos"
-#define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
-#define MPM_SYNC_CHILD_TABLE()
-#define MPM_CHILD_PID(i) (ap_scoreboard_image->servers[0][i].tid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-
-extern int ap_max_child_assigned;
-
-extern server_rec *ap_server_conf;
-extern char ap_coredump_dir[MAX_STRING_LEN];
-extern int ap_threads_per_child;
-
-#endif /* APACHE_MPM_BEOS_H */
diff --git a/server/mpm/beos/mpm_default.h b/server/mpm/beos/mpm_default.h
deleted file mode 100644
index 2517bb8c95..0000000000
--- a/server/mpm/beos/mpm_default.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-/* we use the child (c) as zero in our code... */
-#define AP_ID_FROM_CHILD_THREAD(c, t) t
-/* as the child is always zero, just return the id... */
-#define AP_CHILD_THREAD_FROM_ID(i) 0 , i
-
-/* Number of threads to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_THREADS
-#define DEFAULT_START_THREADS 25
-#endif
-
-/* Maximum number of *free* threads --- more than this, and
- * they will die off.
- */
-
-#ifndef DEFAULT_MAX_FREE_THREADS
-#define DEFAULT_MAX_FREE_THREADS 50
-#endif
-
-/* Minimum --- fewer than this, and more will be created */
-
-#ifndef DEFAULT_MIN_FREE_THREADS
-#define DEFAULT_MIN_FREE_THREADS 5
-#endif
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-
-/* we only ever have 1 main process running... */
-#define HARD_SERVER_LIMIT 1
-
-/* Limit on the threads per process. Clients will be locked out if more than
- * this * HARD_SERVER_LIMIT are needed.
- *
- * We keep this for one reason it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifdef NO_THREADS
-#define HARD_THREAD_LIMIT 1
-#endif
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 50
-#endif
-
-#ifdef NO_THREADS
-#define DEFAULT_THREADS_PER_CHILD 1
-#endif
-
-#ifndef DEFAULT_THREADS_PER_CHILD
-#define DEFAULT_THREADS_PER_CHILD 10
-#endif
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/* Scoreboard file, if there is one */
-#ifndef DEFAULT_SCOREBOARD
-#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/config.m4 b/server/mpm/config.m4
deleted file mode 100644
index 9d2c3fba6a..0000000000
--- a/server/mpm/config.m4
+++ /dev/null
@@ -1,34 +0,0 @@
-AC_MSG_CHECKING(which MPM to use)
-AC_ARG_WITH(mpm,
-[ --with-mpm=MPM Choose the process model for Apache to use.
- MPM={beos,threaded,prefork,spmt_os2,perchild}],[
- APACHE_MPM=$withval
-],[
- if test "x$APACHE_MPM" = "x"; then
- APACHE_MPM=threaded
- fi
-])
-AC_MSG_RESULT($APACHE_MPM)
-
-apache_cv_mpm=$APACHE_MPM
-
-if test "$apache_cv_mpm" = "threaded" -o "$apache_cv_mpm" = "perchild"; then
- APR_CHECK_APR_DEFINE(APR_HAS_THREADS, srclib/apr)
-
- if test "x$ac_cv_define_APR_HAS_THREADS" = "xno"; then
- AC_MSG_RESULT(The currently selected MPM requires threads which your system seems to lack)
- AC_MSG_CHECKING(checking for replacement)
- AC_MSG_RESULT(prefork selected)
- apache_cv_mpm=prefork
- fi
-fi
-
-APACHE_FAST_OUTPUT(server/mpm/Makefile)
-
-MPM_NAME=$apache_cv_mpm
-MPM_DIR=server/mpm/$MPM_NAME
-MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
-
-APACHE_SUBST(MPM_NAME)
-MODLIST="$MODLIST mpm_${MPM_NAME}"
-
diff --git a/server/mpm/experimental/perchild/.cvsignore b/server/mpm/experimental/perchild/.cvsignore
deleted file mode 100644
index 84df257214..0000000000
--- a/server/mpm/experimental/perchild/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.deps
-.libs
-*.lo
-*.la
-Makefile
diff --git a/server/mpm/experimental/perchild/Makefile.in b/server/mpm/experimental/perchild/Makefile.in
deleted file mode 100644
index 374f130646..0000000000
--- a/server/mpm/experimental/perchild/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-LTLIBRARY_NAME = libperchild.la
-LTLIBRARY_SOURCES = perchild.c
-
-include $(top_srcdir)/build/ltlib.mk
diff --git a/server/mpm/experimental/perchild/config5.m4 b/server/mpm/experimental/perchild/config5.m4
deleted file mode 100644
index bd179baed9..0000000000
--- a/server/mpm/experimental/perchild/config5.m4
+++ /dev/null
@@ -1,6 +0,0 @@
-dnl ## XXX - Need a more thorough check of the proper flags to use
-
-if test "$MPM_NAME" = "perchild" ; then
-
- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
-fi
diff --git a/server/mpm/experimental/perchild/mpm.h b/server/mpm/experimental/perchild/mpm.h
deleted file mode 100644
index d24f8b4aba..0000000000
--- a/server/mpm/experimental/perchild/mpm.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "httpd.h"
-#include "mpm_default.h"
-#include "unixd.h"
-
-#ifndef APACHE_MPM_PERCHILD_H
-#define APACHE_MPM_PERCHILD_H
-
-#define PERCHILD_MPM
-
-#define MPM_NAME "Perchild"
-
-#define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
-#define MPM_SYNC_CHILD_TABLE()
-#define MPM_CHILD_PID(i) (ap_child_table[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-
-/* Table of child status */
-#define SERVER_DEAD 0
-#define SERVER_DYING 1
-#define SERVER_ALIVE 2
-
-typedef struct ap_ctable{
- pid_t pid;
- unsigned char status;
-} ap_ctable;
-
-extern int ap_threads_per_child;
-extern int ap_max_daemons_limit;
-extern ap_ctable ap_child_table[HARD_SERVER_LIMIT];
-extern server_rec *ap_server_conf;
-extern char ap_coredump_dir[MAX_STRING_LEN];
-
-#endif /* APACHE_MPM_PERCHILD_H */
diff --git a/server/mpm/experimental/perchild/mpm_default.h b/server/mpm/experimental/perchild/mpm_default.h
deleted file mode 100644
index f462ea8f90..0000000000
--- a/server/mpm/experimental/perchild/mpm_default.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-#define AP_ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t)
-#define AP_CHILD_THREAD_FROM_ID(i) (i / HARD_THREAD_LIMIT), (i % HARD_THREAD_LIMIT)
-
-/* Number of threads to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_THREAD
-#define DEFAULT_START_THREAD 5
-#endif
-
-/* Maximum number of *free* server threads --- more than this, and
- * they will die off.
- */
-
-#ifndef DEFAULT_MAX_SPARE_THREAD
-#define DEFAULT_MAX_SPARE_THREAD 10
-#endif
-
-/* Minimum --- fewer than this, and more will be created */
-
-#ifndef DEFAULT_MIN_SPARE_THREAD
-#define DEFAULT_MIN_SPARE_THREAD 5
-#endif
-
-/* Limit on the threads per process. Clients will be locked out if more than
- * this * HARD_SERVER_LIMIT are needed.
- *
- * We keep this for one reason it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 64
-#endif
-
-/* Number of servers to spawn off by default
- */
-#ifndef DEFAULT_NUM_DAEMON
-#define DEFAULT_NUM_DAEMON 2
-#endif
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_SERVER_LIMIT
-#define HARD_SERVER_LIMIT 8
-#endif
-
-/* File used for accept locking, when we use a file */
-#ifndef DEFAULT_LOCKFILE
-#define DEFAULT_LOCKFILE "logs/accept.lock"
-#endif
-
-/* Scoreboard file, if there is one */
-#ifndef DEFAULT_SCOREBOARD
-#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
-#endif
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/experimental/perchild/perchild.c b/server/mpm/experimental/perchild/perchild.c
deleted file mode 100644
index 0fa14997b1..0000000000
--- a/server/mpm/experimental/perchild/perchild.c
+++ /dev/null
@@ -1,1829 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_hash.h"
-#include "apr_strings.h"
-#include "apr_pools.h"
-#include "apr_portable.h"
-#include "apr_file_io.h"
-#include "apr_signal.h"
-
-#define APR_WANT_IOVEC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#if !APR_HAS_THREADS
-#error The perchild MPM requires APR threads, but they are unavailable.
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h" /* for read_config */
-#include "http_core.h" /* for get_remote_host */
-#include "http_protocol.h"
-#include "http_connection.h"
-#include "ap_mpm.h"
-#include "unixd.h"
-#include "mpm_common.h"
-#include "ap_listen.h"
-#include "mpm_default.h"
-#include "mpm.h"
-#include "scoreboard.h"
-#include "util_filter.h"
-
-/* ### should be APR-ized */
-#include <poll.h>
-#include <grp.h>
-#include <pwd.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <setjmp.h>
-
-/*
- * Actual definitions of config globals
- */
-
-static int threads_to_start = 0; /* Worker threads per child */
-static int min_spare_threads = 0;
-static int max_spare_threads = 0;
-static int max_threads = 0;
-static int max_requests_per_child = 0;
-static const char *ap_pid_fname=NULL;
-static int num_daemons=0;
-static int curr_child_num=0;
-static int workers_may_exit = 0;
-static int requests_this_child;
-static int num_listenfds = 0;
-static apr_socket_t **listenfds;
-static jmp_buf jmpbuffer;
-
-struct child_info_t {
- uid_t uid;
- gid_t gid;
- int sd;
-};
-
-typedef struct {
- const char *sockname; /* The base name for the socket */
- const char *fullsockname; /* socket base name + extension */
- int sd; /* The socket descriptor */
- int sd2; /* The socket descriptor */
-} perchild_server_conf;
-
-typedef struct child_info_t child_info_t;
-
-/* Tables used to determine the user and group each child process should
- * run as. The hash table is used to correlate a server name with a child
- * process.
- */
-static child_info_t child_info_table[HARD_SERVER_LIMIT];
-static int thread_socket_table[HARD_THREAD_LIMIT];
-
-
-struct ap_ctable ap_child_table[HARD_SERVER_LIMIT];
-
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with NumServers changes across SIGWINCH restarts. We use this
- * value to optimize routines that have to scan the entire child table.
- *
- * XXX - It might not be worth keeping this code in. There aren't very
- * many child processes in this MPM.
- */
-int ap_max_daemons_limit = -1;
-int ap_threads_per_child = HARD_THREAD_LIMIT;
-
-char ap_coredump_dir[MAX_STRING_LEN];
-
-module AP_MODULE_DECLARE_DATA mpm_perchild_module;
-
-static apr_file_t *pipe_of_death_in = NULL;
-static apr_file_t *pipe_of_death_out = NULL;
-static apr_lock_t *pipe_of_death_mutex;
-
-/* *Non*-shared http_main globals... */
-
-server_rec *ap_server_conf;
-
-/* one_process --- debugging mode variable; can be set from the command line
- * with the -X flag. If set, this gets you the child_main loop running
- * in the process which originally started up (no detach, no make_child),
- * which is a pretty nice debugging environment. (You'll get a SIGHUP
- * early in standalone_main; just continue through. This is the server
- * trying to kill off any child processes which it might have lying
- * around --- Apache doesn't keep track of their pids, it just sends
- * SIGHUP to the process group, ignoring it in the root process.
- * Continue through and you'll be fine.).
- */
-
-static int one_process = 0;
-
-#ifdef DEBUG_SIGSTOP
-int raise_sigstop_flags;
-#endif
-
-static apr_pool_t *pconf; /* Pool for config stuff */
-static apr_pool_t *pchild; /* Pool for httpd child stuff */
-static apr_pool_t *thread_pool_parent; /* Parent of per-thread pools */
-static apr_lock_t *thread_pool_parent_mutex;
-
-static int child_num;
-static unsigned int my_pid; /* Linux getpid() doesn't work except in
- main thread. Use this instead */
-/* Keep track of the number of worker threads currently active */
-static int worker_thread_count;
-static apr_lock_t *worker_thread_count_mutex;
-static int worker_thread_free_ids[HARD_THREAD_LIMIT];
-static apr_threadattr_t *worker_thread_attr;
-
-/* Keep track of the number of idle worker threads */
-static int idle_thread_count;
-static apr_lock_t *idle_thread_count_mutex;
-
-/* Locks for accept serialization */
-#ifdef NO_SERIALIZED_ACCEPT
-#define SAFE_ACCEPT(stmt) APR_SUCCESS
-#else
-#define SAFE_ACCEPT(stmt) (stmt)
-static apr_lock_t *process_accept_mutex;
-#endif /* NO_SERIALIZED_ACCEPT */
-static const char *lock_fname;
-static apr_lock_t *thread_accept_mutex;
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = ap_max_daemons_limit;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_DYNAMIC;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_STATIC;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = max_threads;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-/* a clean exit from a child with proper cleanup */
-static void clean_child_exit(int code)
-{
- if (pchild) {
- apr_pool_destroy(pchild);
- }
- exit(code);
-}
-
-/* handle all varieties of core dumping signals */
-static void sig_coredump(int sig)
-{
- chdir(ap_coredump_dir);
- apr_signal(sig, SIG_DFL);
- kill(getpid(), sig);
- /* At this point we've got sig blocked, because we're still inside
- * the signal handler. When we leave the signal handler it will
- * be unblocked, and we'll take the signal... and coredump or whatever
- * is appropriate for this particular Unix. In addition the parent
- * will see the real signal we received -- whereas if we called
- * abort() here, the parent would only see SIGABRT.
- */
-}
-
-static void just_die(int sig)
-{
- clean_child_exit(0);
-}
-
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-/* we don't currently track ap_my_generation, but mod_status
- * references it so it must be defined */
-ap_generation_t volatile ap_my_generation=0;
-
-/*
- * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
- * functions to initiate shutdown or restart without relying on signals.
- * Previously this was initiated in sig_term() and restart() signal handlers,
- * but we want to be able to start a shutdown/restart from other sources --
- * e.g. on Win32, from the service manager. Now the service manager can
- * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
- * these functions can also be called by the child processes, since global
- * variables are no longer used to pass on the required action to the parent.
- *
- * These should only be called from the parent process itself, since the
- * parent process will use the shutdown_pending and restart_pending variables
- * to determine whether to shutdown or restart. The child process should
- * call signal_parent() directly to tell the parent to die -- this will
- * cause neither of those variable to be set, which the parent will
- * assume means something serious is wrong (which it will be, for the
- * child to force an exit) and so do an exit anyway.
- */
-
-static void ap_start_shutdown(void)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-/* do a graceful restart if graceful == 1 */
-static void ap_start_restart(int graceful)
-{
-
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- is_graceful = graceful;
- if (is_graceful) {
- apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
- }
-}
-
-static void sig_term(int sig)
-{
- ap_start_shutdown();
-}
-
-static void restart(int sig)
-{
-#ifndef WIN32
- ap_start_restart(sig == SIGWINCH);
-#else
- ap_start_restart(1);
-#endif
-}
-
-static void set_signals(void)
-{
-#ifndef NO_USE_SIGACTION
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
- if (!one_process) {
- sa.sa_handler = sig_coredump;
-#if defined(SA_ONESHOT)
- sa.sa_flags = SA_ONESHOT;
-#elif defined(SA_RESETHAND)
- sa.sa_flags = SA_RESETHAND;
-#endif
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
-#ifdef SIGBUS
- if (sigaction(SIGBUS, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
-#endif
-#ifdef SIGABORT
- if (sigaction(SIGABORT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
-#endif
-#ifdef SIGABRT
- if (sigaction(SIGABRT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
-#endif
-#ifdef SIGILL
- if (sigaction(SIGILL, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
-#endif
- sa.sa_flags = 0;
- }
- sa.sa_handler = sig_term;
- if (sigaction(SIGTERM, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
-#ifdef SIGINT
- if (sigaction(SIGINT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
-#endif
-#ifdef SIGXCPU
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXCPU, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
-#endif
-#ifdef SIGXFSZ
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXFSZ, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
-#endif
-#ifdef SIGPIPE
- sa.sa_handler = SIG_IGN;
- if (sigaction(SIGPIPE, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
-#endif
-
- /* we want to ignore HUPs and WINCH while we're busy processing one */
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sa.sa_handler = restart;
- if (sigaction(SIGHUP, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
- if (sigaction(SIGWINCH, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
-#else
- if (!one_process) {
- apr_signal(SIGSEGV, sig_coredump);
-#ifdef SIGBUS
- apr_signal(SIGBUS, sig_coredump);
-#endif /* SIGBUS */
-#ifdef SIGABORT
- apr_signal(SIGABORT, sig_coredump);
-#endif /* SIGABORT */
-#ifdef SIGABRT
- apr_signal(SIGABRT, sig_coredump);
-#endif /* SIGABRT */
-#ifdef SIGILL
- apr_signal(SIGILL, sig_coredump);
-#endif /* SIGILL */
-#ifdef SIGXCPU
- apr_signal(SIGXCPU, SIG_DFL);
-#endif /* SIGXCPU */
-#ifdef SIGXFSZ
- apr_signal(SIGXFSZ, SIG_DFL);
-#endif /* SIGXFSZ */
- }
-
- apr_signal(SIGTERM, sig_term);
-#ifdef SIGHUP
- apr_signal(SIGHUP, restart);
-#endif /* SIGHUP */
-#ifdef SIGWINCH
- apr_signal(SIGWINCH, restart);
-#endif /* SIGWINCH */
-#ifdef SIGPIPE
- apr_signal(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
-
-#endif
-}
-
-/*****************************************************************
- * Here follows a long bunch of generic server bookkeeping stuff...
- */
-
-int ap_graceful_stop_signalled(void)
-{
- /* XXX - Does this really work? - Manoj */
- return is_graceful;
-}
-
-/*****************************************************************
- * Child process main loop.
- */
-
-static void process_socket(apr_pool_t *p, apr_socket_t *sock, long conn_id)
-{
- conn_rec *current_conn;
- int csd;
- apr_status_t rv;
- int thread_num = conn_id % HARD_THREAD_LIMIT;
-
- if ((rv = apr_os_sock_get(&csd, sock)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "apr_os_sock_get");
- }
-
- if (csd >= FD_SETSIZE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
- "new file descriptor %d is too large; you probably need "
- "to rebuild Apache with a larger FD_SETSIZE "
- "(currently %d)",
- csd, FD_SETSIZE);
- apr_socket_close(sock);
- return;
- }
-
- if (thread_socket_table[thread_num] < 0) {
- ap_sock_disable_nagle(sock);
- }
-
- current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id);
- if (current_conn) {
- ap_process_connection(current_conn);
- ap_lingering_close(current_conn);
- }
-}
-
-static void *worker_thread(void *);
-
-/* Starts a thread as long as we're below max_threads */
-static int start_thread(void)
-{
- apr_thread_t *thread;
- int rc;
-
- apr_lock_acquire(worker_thread_count_mutex);
- if (worker_thread_count < max_threads - 1) {
- if ((rc = apr_thread_create(&thread, worker_thread_attr, worker_thread,
- &worker_thread_free_ids[worker_thread_count], pchild))) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, rc, ap_server_conf,
- "apr_thread_create: unable to create worker thread");
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again if we exit. */
- sleep(10);
- workers_may_exit = 1;
- apr_lock_release(worker_thread_count_mutex);
- return 0;
- }
- else {
- worker_thread_count++;
- }
- }
- else {
- static int reported = 0;
-
- if (!reported) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
- "server reached MaxThreadsPerChild setting, consider raising the"
- " MaxThreadsPerChild or NumServers settings");
- reported = 1;
- }
- apr_lock_release(worker_thread_count_mutex);
- return 0;
- }
- apr_lock_release(worker_thread_count_mutex);
- return 1;
-
-}
-/* Sets workers_may_exit if we received a character on the pipe_of_death */
-static void check_pipe_of_death(void)
-{
- apr_lock_acquire(pipe_of_death_mutex);
- if (!workers_may_exit) {
- int ret;
- char pipe_read_char;
- apr_size_t n = 1;
-
- ret = apr_recv(listenfds[0], &pipe_read_char, &n);
- if (APR_STATUS_IS_EAGAIN(ret)) {
- /* It lost the lottery. It must continue to suffer
- * through a life of servitude. */
- }
- else {
- /* It won the lottery (or something else is very
- * wrong). Embrace death with open arms. */
- workers_may_exit = 1;
- }
- }
- apr_lock_release(pipe_of_death_mutex);
-}
-
-/* idle_thread_count should be incremented before starting a worker_thread */
-
-static void *worker_thread(void *arg)
-{
- apr_socket_t *csd = NULL;
- apr_pool_t *tpool; /* Pool for this thread */
- apr_pool_t *ptrans; /* Pool for per-transaction stuff */
- apr_socket_t *sd = NULL;
- int srv;
- int curr_pollfd, last_pollfd = 0;
- int thread_just_started = 1;
- int thread_num = *((int *) arg);
- long conn_id = child_num * HARD_THREAD_LIMIT + thread_num;
- apr_pollfd_t *pollset;
- int n;
- apr_status_t rv;
-
- apr_lock_acquire(thread_pool_parent_mutex);
- apr_pool_create(&tpool, thread_pool_parent);
- apr_lock_release(thread_pool_parent_mutex);
- apr_pool_create(&ptrans, tpool);
-
- (void) ap_update_child_status(child_num, thread_num, SERVER_STARTING,
- (request_rec *) NULL);
-
- apr_poll_setup(&pollset, num_listenfds+1, tpool);
- for(n=0 ; n <= num_listenfds ; ++n) {
- apr_poll_socket_add(pollset, listenfds[n], APR_POLLIN);
- }
-
- while (!workers_may_exit) {
- workers_may_exit |= (max_requests_per_child != 0) && (requests_this_child <= 0);
- if (workers_may_exit) break;
- if (!thread_just_started) {
- apr_lock_acquire(idle_thread_count_mutex);
- if (idle_thread_count < max_spare_threads) {
- idle_thread_count++;
- apr_lock_release(idle_thread_count_mutex);
- }
- else {
- apr_lock_release(idle_thread_count_mutex);
- break;
- }
- }
- else {
- thread_just_started = 0;
- }
-
- (void) ap_update_child_status(child_num, thread_num, SERVER_READY,
- (request_rec *) NULL);
-
- apr_lock_acquire(thread_accept_mutex);
- if (workers_may_exit) {
- apr_lock_release(thread_accept_mutex);
- break;
- }
- if ((rv = SAFE_ACCEPT(apr_lock_acquire(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_acquire failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
-
- while (!workers_may_exit) {
- apr_int16_t event;
- srv = apr_poll(pollset, &n, -1);
-
- if (srv != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(srv)) {
- continue;
- }
-
- /* apr_poll() will only return errors in catastrophic
- * circumstances. Let's try exiting gracefully, for now. */
- ap_log_error(APLOG_MARK, APLOG_ERR, srv, (const server_rec *)
- ap_server_conf, "apr_poll: (listen)");
- workers_may_exit = 1;
- }
- if (workers_may_exit) break;
-
- apr_poll_revents_get(&event, listenfds[0], pollset);
- if (event & APR_POLLIN) {
- /* A process got a signal on the shutdown pipe. Check if we're
- * the lucky process to die. */
- check_pipe_of_death();
- continue;
- }
-
- apr_poll_revents_get(&event, listenfds[1], pollset);
- if (event & APR_POLLIN || event & APR_POLLOUT) {
- /* This request is from another child in our current process.
- * We should set a flag here, and then below we will read
- * two bytes (the socket number and the NULL byte.
- */
- thread_socket_table[thread_num] = -2;
- goto got_from_other_child;
- }
-
- if (num_listenfds == 1) {
- sd = ap_listeners->sd;
- goto got_fd;
- }
- else {
- /* find a listener */
- curr_pollfd = last_pollfd;
- do {
- curr_pollfd++;
- if (curr_pollfd > num_listenfds) {
- curr_pollfd = 1;
- }
- /* XXX: Should we check for POLLERR? */
- apr_poll_revents_get(&event, listenfds[curr_pollfd], pollset);
- if (event & APR_POLLIN) {
- last_pollfd = curr_pollfd;
- sd = listenfds[curr_pollfd];
- goto got_fd;
- }
- } while (curr_pollfd != last_pollfd);
- }
- }
- got_fd:
- if (!workers_may_exit) {
- if ((rv = apr_accept(&csd, sd, ptrans)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "apr_accept");
- }
- if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- apr_lock_release(thread_accept_mutex);
- apr_lock_acquire(idle_thread_count_mutex);
- if (idle_thread_count > min_spare_threads) {
- idle_thread_count--;
- }
- else {
- if (!start_thread()) {
- idle_thread_count--;
- }
- }
- apr_lock_release(idle_thread_count_mutex);
- got_from_other_child:
- if (thread_socket_table[thread_num] == -2) {
- struct msghdr msg;
- struct cmsghdr *cmsg;
- char sockname[80];
- struct iovec iov;
- int ret, sd, dp;
-
- iov.iov_base = sockname;
- iov.iov_len = 80;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- cmsg = apr_palloc(ptrans, sizeof(*cmsg) + sizeof(sd));
- cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sd);
- msg.msg_control = (caddr_t)cmsg;
- msg.msg_controllen = cmsg->cmsg_len;
- msg.msg_flags = 0;
-
- ret = recvmsg(child_info_table[child_num].sd, &msg, 0);
-
- memcpy(&dp, CMSG_DATA(cmsg), sizeof(dp));
-
- thread_socket_table[thread_num] = dp;
- apr_os_sock_put(&csd, &child_info_table[child_num].sd, ptrans);
- }
- if (setjmp(jmpbuffer) != 1) {
- process_socket(ptrans, csd, conn_id);
- }
- else {
- thread_socket_table[thread_num] = -1;
- }
- requests_this_child--;
- } else {
- if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- apr_lock_release(thread_accept_mutex);
- apr_lock_acquire(idle_thread_count_mutex);
- idle_thread_count--;
- apr_lock_release(idle_thread_count_mutex);
- break;
- }
- apr_pool_clear(ptrans);
- }
-
- apr_lock_acquire(thread_pool_parent_mutex);
- ap_update_child_status(child_num, thread_num, SERVER_DEAD,
- (request_rec *) NULL);
- apr_pool_destroy(tpool);
- apr_lock_release(thread_pool_parent_mutex);
- apr_lock_acquire(worker_thread_count_mutex);
- worker_thread_count--;
- worker_thread_free_ids[worker_thread_count] = thread_num;
- if (worker_thread_count == 0) {
- /* All the threads have exited, now finish the shutdown process
- * by signalling the sigwait thread */
- kill(my_pid, SIGTERM);
- }
- apr_lock_release(worker_thread_count_mutex);
-
- return NULL;
-}
-
-/* Set group privileges.
- *
- * Note that we use the username as set in the config files, rather than
- * the lookup of to uid --- the same uid may have multiple passwd entries,
- * with different sets of groups for each.
- */
-
-static int set_group_privs(uid_t uid, gid_t gid)
-{
- if (!geteuid()) {
- const char *name;
-
- /* Get username if passed as a uid */
-
- struct passwd *ent;
-
- if ((ent = getpwuid(uid)) == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "getpwuid: couldn't determine user name from uid %u, "
- "you probably need to modify the User directive",
- (unsigned)uid);
- return -1;
- }
-
- name = ent->pw_name;
-
- /*
- * Set the GID before initgroups(), since on some platforms
- * setgid() is known to zap the group list.
- */
- if (setgid(gid) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "setgid: unable to set group id to Group %u",
- (unsigned)gid);
- return -1;
- }
-
- /* Reset `groups' attributes. */
-
- if (initgroups(name, gid) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "initgroups: unable to set groups for User %s "
- "and Group %u", name, (unsigned)gid);
- return -1;
- }
- }
- return 0;
-}
-
-
-static int perchild_setup_child(int childnum)
-{
- child_info_t *ug = &child_info_table[childnum];
-
- if (ug->uid == -1 && ug->gid == -1) {
- return unixd_setup_child();
- }
- if (set_group_privs(ug->uid, ug->gid)) {
- return -1;
- }
- /* Only try to switch if we're running as root */
- if (!geteuid() && (
-#ifdef _OSD_POSIX
- os_init_job_environment(server_conf, unixd_config.user_name, one_process) != 0 ||
-#endif
- setuid(ug->uid) == -1)) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "setuid: unable to change to uid: %ld",
- (long) ug->uid);
- return -1;
- }
- return 0;
-}
-
-static int check_signal(int signum)
-{
- switch (signum) {
- case SIGTERM:
- case SIGINT:
- just_die(signum);
- return 1;
- }
- return 0;
-}
-
-static void child_main(int child_num_arg)
-{
- int i;
- ap_listen_rec *lr;
- apr_status_t rv;
- apr_thread_t *thread;
-
- my_pid = getpid();
- child_num = child_num_arg;
- apr_pool_create(&pchild, pconf);
-
- /*stuff to do before we switch id's, so we have permissions.*/
-
- rv = SAFE_ACCEPT(apr_lock_child_init(&process_accept_mutex, lock_fname,
- pchild));
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "Couldn't initialize cross-process lock in child");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- if (perchild_setup_child(child_num)) {
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- ap_run_child_init(pchild, ap_server_conf);
-
- /*done with init critical section */
-
- apr_setup_signal_thread();
-
- requests_this_child = max_requests_per_child;
-
- /* Set up the pollfd array, num_listenfds + 1 for the pipe and 1 for
- * the child socket.
- */
- listenfds = apr_pcalloc(pchild, sizeof(*listenfds) * (num_listenfds + 2));
-#if APR_FILES_AS_SOCKETS
- apr_socket_from_file(&listenfds[0], pipe_of_death_in);
-#endif
-
- /* The child socket */
- apr_os_sock_put(&listenfds[1], &child_info_table[child_num].sd, pchild);
-
- num_listenfds++;
- for (lr = ap_listeners, i = 2; i <= num_listenfds; lr = lr->next, ++i)
- listenfds[i]=lr->sd;
-
- /* Setup worker threads */
-
- if (threads_to_start > max_threads) {
- threads_to_start = max_threads;
- }
- idle_thread_count = threads_to_start;
- worker_thread_count = 0;
- for (i = 0; i < max_threads; i++) {
- worker_thread_free_ids[i] = i;
- }
- apr_pool_create(&thread_pool_parent, pchild);
- apr_lock_create(&thread_pool_parent_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&idle_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&pipe_of_death_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&thread_accept_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
-
- apr_threadattr_create(&worker_thread_attr, pchild);
- apr_threadattr_detach_set(worker_thread_attr, 1);
-
- /* We are creating worker threads right now */
- for (i=0; i < threads_to_start; i++) {
- /* start_thread shouldn't fail here */
- if (!start_thread()) {
- break;
- }
- }
-
- apr_signal_thread(check_signal);
-}
-
-static int make_child(server_rec *s, int slot)
-{
- int pid;
-
- if (slot + 1 > ap_max_daemons_limit) {
- ap_max_daemons_limit = slot + 1;
- }
-
- if (one_process) {
- set_signals();
- ap_child_table[slot].pid = getpid();
- ap_child_table[slot].status = SERVER_ALIVE;
- child_main(slot);
- }
- (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
-
- if ((pid = fork()) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
- "fork: Unable to fork new process");
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again. */
- sleep(10);
-
- return -1;
- }
-
- if (!pid) {
-#ifdef AIX_BIND_PROCESSOR
- /* By default, AIX binds to a single processor. This bit unbinds
- children which will then bind to another CPU.
- */
-#include <sys/processor.h>
- int status = bindprocessor(BINDPROCESS, (int)getpid(),
- PROCESSOR_CLASS_ANY);
- if (status != OK)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno,
- ap_server_conf, "processor unbind failed %d", status);
-#endif
-
- RAISE_SIGSTOP(MAKE_CHILD);
-
- /* XXX - For an unthreaded server, a signal handler will be necessary
- apr_signal(SIGTERM, just_die);
- */
- child_main(slot);
- clean_child_exit(0);
- }
- /* else */
- ap_child_table[slot].pid = pid;
- ap_child_table[slot].status = SERVER_ALIVE;
-
- return 0;
-}
-
-/* start up a bunch of children */
-static int startup_children(int number_to_start)
-{
- int i;
-
- for (i = 0; number_to_start && i < num_daemons; ++i) {
- if (ap_child_table[i].pid) {
- continue;
- }
- if (make_child(ap_server_conf, i) < 0) {
- break;
- }
- --number_to_start;
- }
- return number_to_start;
-}
-
-
-/*
- * spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
-static void perform_child_maintenance(void)
-{
- int i;
- int free_length;
- int free_slots[MAX_SPAWN_RATE];
- int last_non_dead = -1;
-
- /* initialize the free_list */
- free_length = 0;
-
- for (i = 0; i < num_daemons; ++i) {
- if (ap_child_table[i].pid == 0) {
- if (free_length < spawn_rate) {
- free_slots[free_length] = i;
- ++free_length;
- }
- }
- else {
- last_non_dead = i;
- }
-
- if (i >= ap_max_daemons_limit && free_length >= spawn_rate) {
- break;
- }
- }
- ap_max_daemons_limit = last_non_dead + 1;
-
- if (free_length > 0) {
- for (i = 0; i < free_length; ++i) {
- make_child(ap_server_conf, free_slots[i]);
- }
- /* the next time around we want to spawn twice as many if this
- * wasn't good enough, but not if we've just done a graceful
- */
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
- }
- else if (spawn_rate < MAX_SPAWN_RATE) {
- spawn_rate *= 2;
- }
- }
- else {
- spawn_rate = 1;
- }
-}
-
-static void server_main_loop(int remaining_children_to_start)
-{
- int child_slot;
- apr_wait_t status;
- apr_proc_t pid;
- int i;
-
- while (!restart_pending && !shutdown_pending) {
- ap_wait_or_timeout(&status, &pid, pconf);
-
- if (pid.pid != -1) {
- ap_process_child_status(&pid, status);
- /* non-fatal death... note that it's gone in the child table and
- * clean out the status table. */
- child_slot = -1;
- for (i = 0; i < ap_max_daemons_limit; ++i) {
- if (ap_child_table[i].pid == pid.pid) {
- child_slot = i;
- break;
- }
- }
- if (child_slot >= 0) {
- ap_child_table[child_slot].pid = 0;
- ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
-
-
- if (remaining_children_to_start
- && child_slot < num_daemons) {
- /* we're still doing a 1-for-1 replacement of dead
- * children with new children
- */
- make_child(ap_server_conf, child_slot);
- --remaining_children_to_start;
- }
-#if APR_HAS_OTHER_CHILD
- }
- else if (apr_proc_other_child_read(&pid, status) == 0) {
- /* handled */
-#endif
- }
- else if (is_graceful) {
- /* Great, we've probably just lost a slot in the
- * child table. Somehow we don't know about this
- * child.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0,
- ap_server_conf,
- "long lost child came home! (pid %ld)",
- (long)pid.pid);
- }
- /* Don't perform idle maintenance when a child dies,
- * only do it when there's a timeout. Remember only a
- * finite number of children can die, and it's pretty
- * pathological for a lot to die suddenly.
- */
- continue;
- }
- else if (remaining_children_to_start) {
- /* we hit a 1 second timeout in which none of the previous
- * generation of children needed to be reaped... so assume
- * they're all done, and pick up the slack if any is left.
- */
- remaining_children_to_start = \
- startup_children(remaining_children_to_start);
- /* In any event we really shouldn't do the code below because
- * few of the servers we just started are in the IDLE state
- * yet, so we'd mistakenly create an extra server.
- */
- continue;
- }
-
- perform_child_maintenance();
- }
-}
-
-int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
-{
- int remaining_children_to_start;
- int i;
- apr_status_t rv;
- apr_size_t one = 1;
-
- pconf = _pconf;
- ap_server_conf = s;
- if ((rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out, pconf))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_create (pipe_of_death)");
- exit(1);
- }
- if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_timeout_set (pipe_of_death)");
- exit(1);
- }
- ap_server_conf = s;
- if ((num_listenfds = ap_setup_listeners(ap_server_conf)) < 1) {
- /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
- "no listening sockets available, shutting down");
- return 1;
- }
- ap_log_pid(pconf, ap_pid_fname);
-
- /* Initialize cross-process accept lock */
- lock_fname = apr_psprintf(_pconf, "%s.%u",
- ap_server_root_relative(_pconf, lock_fname),
- my_pid);
- rv = SAFE_ACCEPT(apr_lock_create(&process_accept_mutex, APR_MUTEX,
- APR_CROSS_PROCESS, lock_fname, _pconf));
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
- "Couldn't create cross-process lock");
- return 1;
- }
-
- if (!is_graceful) {
- ap_create_scoreboard(pconf, SB_SHARED);
- }
- /* Initialize the child table */
- if (!is_graceful) {
- for (i = 0; i < HARD_SERVER_LIMIT; i++) {
- ap_child_table[i].pid = 0;
- }
- }
-
- set_signals();
-
- /* If we're doing a graceful_restart then we're going to see a lot
- * of children exiting immediately when we get into the main loop
- * below (because we just sent them SIGWINCH). This happens pretty
- * rapidly... and for each one that exits we'll start a new one until
- * we reach at least daemons_min_free. But we may be permitted to
- * start more than that, so we'll just keep track of how many we're
- * supposed to start up without the 1 second penalty between each fork.
- */
- remaining_children_to_start = num_daemons;
- if (!is_graceful) {
- remaining_children_to_start = \
- startup_children(remaining_children_to_start);
- }
- else {
- /* give the system some time to recover before kicking into
- * exponential mode */
- hold_off_on_exponential_spawning = 10;
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "%s configured -- resuming normal operations",
- ap_get_server_version());
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "Server built: %s", ap_get_server_built());
- restart_pending = shutdown_pending = 0;
-
- server_main_loop(remaining_children_to_start);
-
- if (shutdown_pending) {
- /* Time to gracefully shut down:
- * Kill child processes, tell them to call child_exit, etc...
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
- "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
-
- /* cleanup pid file on normal shutdown */
- {
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
- ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
- ap_server_conf, "caught SIGTERM, shutting down");
-
- return 1;
- }
-
- /* we've been told to restart */
- apr_signal(SIGHUP, SIG_IGN);
-
- if (one_process) {
- /* not worth thinking about */
- return 1;
- }
-
- if (is_graceful) {
- char char_of_death = '!';
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGWINCH received. Doing graceful restart");
-
- /* This is mostly for debugging... so that we know what is still
- * gracefully dealing with existing request.
- */
-
- for (i = 0; i < num_daemons; ++i) {
- if (ap_child_table[i].pid) {
- ap_child_table[i].status = SERVER_DYING;
- }
- }
- /* give the children the signal to die */
- for (i = 0; i < num_daemons;) {
- if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(rv)) continue;
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
- "write pipe_of_death");
- }
- i++;
- }
- }
- else {
- /* Kill 'em all. Since the child acts the same on the parents SIGTERM
- * and a SIGHUP, we may as well use the same signal, because some user
- * pthreads are stealing signals from us left and right.
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
- "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
- ap_server_conf, "SIGHUP received. Attempting to restart");
- }
- return 0;
-}
-
-static void perchild_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- static int restart_num = 0;
- int no_detach = 0;
- int i;
-
- one_process = !!ap_exists_config_define("ONE_PROCESS");
- no_detach = !!ap_exists_config_define("NO_DETACH");
-
- /* sigh, want this only the second time around */
- if (restart_num++ == 1) {
- is_graceful = 0;
-
- if (!one_process && !no_detach) {
- apr_proc_detach();
- }
-
- my_pid = getpid();
- }
-
- unixd_pre_config(ptemp);
- ap_listen_pre_config();
- num_daemons = DEFAULT_NUM_DAEMON;
- threads_to_start = DEFAULT_START_THREAD;
- min_spare_threads = DEFAULT_MIN_SPARE_THREAD;
- max_spare_threads = DEFAULT_MAX_SPARE_THREAD;
- max_threads = HARD_THREAD_LIMIT;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_scoreboard_fname = DEFAULT_SCOREBOARD;
- lock_fname = DEFAULT_LOCKFILE;
- max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
- curr_child_num = 0;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-
- for (i = 0; i < HARD_SERVER_LIMIT; i++) {
- child_info_table[i].uid = -1;
- child_info_table[i].gid = -1;
- child_info_table[i].sd = -1;
- }
- for (i = 0; i < HARD_THREAD_LIMIT; i++) {
- thread_socket_table[i] = -1;
- }
-}
-
-static int pass_request(request_rec *r)
-{
- apr_socket_t *thesock = r->connection->client_socket;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- int sfd;
- struct iovec iov;
- apr_bucket_brigade *bb = apr_brigade_create(r->pool);
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(r->server->module_config,
- &mpm_perchild_module);
- char *foo;
- apr_size_t len;
- apr_size_t readbytes = 0;
-
- apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool);
- len = strlen(foo);
-
- apr_pool_userdata_set(NULL, "PERCHILD_BUFFER", apr_pool_cleanup_null,
- r->connection->pool);
-
- apr_os_sock_get(&sfd, thesock);
-
- iov.iov_base = NULL;
- iov.iov_len = 0;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd));
- cmsg->cmsg_len = sizeof(*cmsg) + sizeof(int);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
-
- memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd));
-
- msg.msg_control = (caddr_t)cmsg;
- msg.msg_controllen = cmsg->cmsg_len;
- msg.msg_flags=0;
-
- if (sendmsg(sconf->sd2, &msg, 0) == -1) {
- apr_pool_destroy(r->pool);
- return -1;
- }
-
- write(sconf->sd2, foo, len);
-
- while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING, &readbytes) == APR_SUCCESS) {
- apr_bucket *e;
- APR_BRIGADE_FOREACH(e, bb) {
- const char *str;
-
- apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
- write(sconf->sd2, str, len);
- }
- }
-
- apr_pool_destroy(r->pool);
- return 1;
-}
-
-static char *make_perchild_socket(const char *fullsockname, int sd[2])
-{
- socketpair(PF_UNIX, SOCK_STREAM, 0, sd);
- return NULL;
-}
-
-
-static void perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
-{
- int i;
- server_rec *sr;
- perchild_server_conf *sconf;
- int def_sd[2];
-
- def_sd[0] = -1;
- def_sd[1] = -1;
-
- for (sr = s; sr; sr = sr->next) {
- sconf = (perchild_server_conf *)ap_get_module_config(sr->module_config,
- &mpm_perchild_module);
-
- if (sconf->sd == -1) {
- sconf->fullsockname = apr_pstrcat(sr->process->pool,
- sconf->sockname, ".DEFAULT", NULL);
- if (def_sd[0] == -1) {
- if (!make_perchild_socket(sconf->fullsockname, def_sd)) {
- /* log error */
- }
- }
- sconf->sd = def_sd[0];
- sconf->sd2 = def_sd[1];
- }
- }
-
- for (i = 0; i < num_daemons; i++) {
- if (child_info_table[i].uid == -1) {
- child_info_table[i].sd = def_sd[0];
- }
- }
-}
-
-static int perchild_post_read(request_rec *r)
-{
- ap_filter_t *f = r->connection->input_filters;
- int thread_num = r->connection->id % HARD_THREAD_LIMIT;
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(r->server->module_config,
- &mpm_perchild_module);
-
- while (f) {
- if (!strcmp("PERCHILD_BUFFER", f->frec->name)) {
- ap_remove_output_filter(f);
- break;
- }
- f = f->next;
- }
-
- if (thread_socket_table[thread_num] != -1) {
- apr_socket_t *csd = NULL;
-
- apr_os_sock_put(&csd, &thread_socket_table[thread_num],
- r->connection->pool);
- ap_sock_disable_nagle(csd);
- r->connection->client_socket = csd;
- return OK;
- }
- else {
- if (sconf->sd != child_info_table[child_num].sd) {
- if (pass_request(r) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0,
- ap_server_conf, "Could not pass request to proper "
- "child, request will not be honored.");
- }
- longjmp(jmpbuffer, 1);
- }
- return OK;
- }
- return OK;
-}
-
-static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_bucket *e;
- apr_status_t rv;
- char *buffer = NULL;
- const char *str;
- apr_size_t len;
-
- if ((rv = ap_get_brigade(f->next, b, mode, readbytes)) != APR_SUCCESS) {
- return rv;
- }
-
- apr_pool_userdata_get((void **)&buffer, "PERCHILD_BUFFER", f->c->pool);
-
- APR_BRIGADE_FOREACH(e, b) {
- if (e->length != 0) {
- apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
-
- if (buffer == NULL) {
- buffer = apr_pstrndup(f->c->pool, str, len);
- }
- else {
- buffer = apr_pstrcat(f->c->pool, buffer,
- apr_pstrndup(f->c->pool, str, len), NULL);
- }
- }
- }
- apr_pool_userdata_set(buffer, "PERCHILD_BUFFER", apr_pool_cleanup_null, f->c->pool);
-
- return APR_SUCCESS;
-}
-
-static int perchild_pre_connection(conn_rec *c)
-{
- ap_add_input_filter("PERCHILD_BUFFER", NULL, NULL, c);
- return OK;
-}
-
-static void perchild_hooks(apr_pool_t *p)
-{
- one_process = 0;
-
- ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_pre_connection(perchild_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
-
- /* This must be run absolutely first. If this request isn't for this
- * server then we need to forward it to the proper child. No sense
- * tying up this server running more post_read request hooks if it is
- * just going to be forwarded along.
- */
- ap_hook_post_read_request(perchild_post_read, NULL, NULL, APR_HOOK_REALLY_FIRST);
- ap_register_input_filter("PERCHILD_BUFFER", perchild_buffer, AP_FTYPE_CONTENT);
-}
-
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in <VirtualHost>";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_scoreboard_fname = arg;
- return NULL;
-}
-
-static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- lock_fname = arg;
- return NULL;
-}
-static const char *set_num_daemons (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- num_daemons = atoi(arg);
- if (num_daemons > HARD_SERVER_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: NumServers of %d exceeds compile time limit "
- "of %d servers,", num_daemons, HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering NumServers to %d. To increase, please "
- "see the", HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_SERVER_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- num_daemons = HARD_SERVER_LIMIT;
- }
- else if (num_daemons < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require NumServers > 0, setting to 1");
- num_daemons = 1;
- }
- return NULL;
-}
-
-static const char *set_threads_to_start (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- threads_to_start = atoi(arg);
- if (threads_to_start > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: StartThreads of %d exceeds compile time"
- " limit of %d threads,", threads_to_start,
- HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering StartThreads to %d. To increase, please"
- " see the", HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_THREAD_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- }
- else if (threads_to_start < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require StartThreads > 0, setting to 1");
- threads_to_start = 1;
- }
- return NULL;
-}
-
-static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- min_spare_threads = atoi(arg);
- if (min_spare_threads <= 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set to non-positive.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Resetting to 1 to avoid almost certain Apache failure.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Please read the documentation.");
- min_spare_threads = 1;
- }
-
- return NULL;
-}
-
-static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_spare_threads = atoi(arg);
- if (max_spare_threads >= HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set higher than");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
- max_spare_threads = HARD_THREAD_LIMIT;
- }
- return NULL;
-}
-
-static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_threads = atoi(arg);
- if (max_threads > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MaxThreadsPerChild set higher than");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
- max_threads = HARD_THREAD_LIMIT;
- }
- return NULL;
-}
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_requests_per_child = atoi(arg);
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-static const char *set_child_per_uid(cmd_parms *cmd, void *dummy, const char *u,
- const char *g, const char *num)
-{
- int i;
- int max_this_time = atoi(num) + curr_child_num;
- for (i = curr_child_num; i < max_this_time; i++, curr_child_num++); {
- child_info_t *ug = &child_info_table[i - 1];
-
- if (i > num_daemons) {
- return "Trying to use more child ID's than NumServers. Increase "
- "NumServers in your config file.";
- }
-
- ug->uid = atoi(u);
- ug->gid = atoi(g);
- }
- return NULL;
-}
-
-static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid,
- const char *gid)
-{
- int i;
- int u = atoi(uid);
- int g = atoi(gid);
- const char *errstr;
- int socks[2];
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(cmd->server->module_config,
- &mpm_perchild_module);
-
- sconf->fullsockname = apr_pstrcat(cmd->pool, sconf->sockname, ".", uid, ":", gid, NULL);
-
- if ((errstr = make_perchild_socket(sconf->fullsockname, socks))) {
- return errstr;
- }
-
- sconf->sd = socks[0];
- sconf->sd2 = socks[1];
-
- for (i = 0; i < num_daemons; i++) {
- if (u == child_info_table[i].uid && g == child_info_table[i].gid) {
- child_info_table[i].sd = sconf->sd;
- }
- }
-
- return NULL;
-}
-
-
-static const command_rec perchild_cmds[] = {
-UNIX_DAEMON_COMMANDS
-LISTEN_COMMANDS
-AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
- "A file for logging the server process ID"),
-AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
- "A file for Apache to maintain runtime process management information"),
-AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
- "The lockfile used when Apache needs to lock the accept() call"),
-AP_INIT_TAKE1("NumServers", set_num_daemons, NULL, RSRC_CONF,
- "Number of children alive at the same time"),
-AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF,
- "Number of threads each child creates"),
-AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
- "Minimum number of idle threads per child, to handle request spikes"),
-AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
- "Maximum number of idle threads per child"),
-AP_INIT_TAKE1("MaxThreadsPerChild", set_max_threads, NULL, RSRC_CONF,
- "Maximum number of threads per child"),
-AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
- "Maximum number of requests a particular child serves before dying."),
-AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
- "The location of the directory Apache changes to before dumping core"),
-AP_INIT_TAKE3("ChildperUserID", set_child_per_uid, NULL, RSRC_CONF,
- "Specify a User and Group for a specific child process."),
-AP_INIT_TAKE2("AssignUserID", assign_childuid, NULL, RSRC_CONF,
- "Tie a virtual host to a specific child process."),
-{ NULL }
-};
-
-static void *perchild_create_config(apr_pool_t *p, server_rec *s)
-{
- perchild_server_conf *c =
- (perchild_server_conf *) apr_pcalloc(p, sizeof(perchild_server_conf));
-
- c->sd = -1;
- return c;
-}
-
-module AP_MODULE_DECLARE_DATA mpm_perchild_module = {
- MPM20_MODULE_STUFF,
- NULL, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- perchild_create_config, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- perchild_cmds, /* command apr_table_t */
- perchild_hooks /* register_hooks */
-};
-
diff --git a/server/mpm/monitoring-services.txt b/server/mpm/monitoring-services.txt
deleted file mode 100644
index 2466589025..0000000000
--- a/server/mpm/monitoring-services.txt
+++ /dev/null
@@ -1,94 +0,0 @@
-From: William A. Rowe, Jr.
-Date: June 7th '00
-Subject: service monitoring in Apache 1.3.13
-
-The concept for a taskbar monitor has been thrown around
-for a very long while. 1.3.13 introduced Win9x services,
-and that added fuel to the mix. Here are some sideband
-observations I've made for other developers...
-
-About Apache as a console, don't start Apache hidden without
-any command line arguments if you want to launch it yourself
-in a hidden window (it will do the classic test for
-AllocConsole/FreeConsole)... drop in some arguments such as
-the -f or -r option and it will fly without thinking it is a
-service under 9x and NT.
-
-Rule two, don't use --ntservice as an argument, ever. Only
-the Windows NT Service Control Manager is allowed to pass that
-flag, and only that flag, when it runs Apache.exe. Do use
---ntservice as the sole argument to the executable name if
-you are installing an Apache NT service yourself.
-
-Rule three, use -k start and -n name when maintaining the
-HKLM/Software/Microsoft/Windows/CurrentVersion/RunServices
-list, since there is no other way for Apache to know what
-the service is named :) And look at any 9x installed service's
-RunServices entry in the registry for the start service semantic.
-
-Rule four, use the WinNT Service Control Manager exclusively
-for starting, stopping and restarting Apache as an NT service.
-The restart signal is the value 128, as documented in service.h
-and service.c - this will continue to work in Apache 2.0. If
-it fails, you are handling an older version (pre 1.3.13) of
-Apache, and need to stop and then start the service instead.
-
-Rule five, use the legacy pid-named events to signal Win9x
-service Apache to restart and stop the service. But don't
-bother looking for httpd.pid files... you can get the pid
-right from the hidden service control window. Apache 1.3.13
-and 2.x create a hidden window named for the name of the
-service (without the spaces), with a window class of
-"ApacheWin95ServiceMonitor", so can use FindWindow to track
-down running Win9x services. See the service.c code for how
-I accomplished this pretty simply in the -k stop/-k restart
-handler.
-
-Taskbar Monitor App
--------------------
-
-Basic requirements: a C code application using strictly the
-Win32 API, and not MFC or other Win32 frameworks. Could use
-the service.c module to share some basic functions. That
-module could be extended in Apache 2.0 to make this all easier.
-
-I think we are looking for an external app that simply acts
-as a monitor or allows a stopped service to be started. If
-the user logs off, we loose the monitor app, but installed as
-a shortcut in the Start group or in the registry key
-HKLM/Software/Microsoft/Windows/CurrentVersion/Run
-we will be just fine. I'd like to see the monitor run only
-one instance to monitor all running services, for memory
-and resource conservation.
-
-I was thinking that the hover/iconbar title would tell them
-"Test service is running", or "Test service is stopped".
-If they left click, they could stop or restart, or simply
-start if it is stopped. There could be a preference that
-each service doesn't get it's own individual task icon unless
-it is running, if it is a manual start service (or missing
-from the RunServices list, which is the equivilant under 9x).
-
-If a specific service is set to Auto start or is in the
-RunServices Win9x registry key, we must show them the stopped
-icon, of course. We might also keep the icon for any running
-service that stops abruptly. But there could be a 'single
-icon' option for the taskbar icon monitor that says show only
-a single status icon, for simplicity if the administrator runs
-many Apache services.
-
-But I was hoping that any right click would provide a menu
-of all Apache services with their status. e.g.
- Test service is stopped
- Apache_2 service is running
- MyWeb service is running
-and each would do the logical submenu, same as if that
-specific taskbar icon were left clicked, offering to start or
-offering to stop or restart the server, as appropriate.
-
-Finally, to identify all installed Apache services, just query
-the registry key HKLM\SYSTEM\CurrentControlSet\Services for any
-key that has the ImagePath value of "...\Apache.exe"... (quotes
-are significant here, if the leading quote is ommitted the
-entire string ends with the text \Apache.exe - based on Apache's
-own service installer in every released version.)
diff --git a/server/mpm/perchild/.cvsignore b/server/mpm/perchild/.cvsignore
deleted file mode 100644
index 84df257214..0000000000
--- a/server/mpm/perchild/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.deps
-.libs
-*.lo
-*.la
-Makefile
diff --git a/server/mpm/perchild/Makefile.in b/server/mpm/perchild/Makefile.in
deleted file mode 100644
index 374f130646..0000000000
--- a/server/mpm/perchild/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-LTLIBRARY_NAME = libperchild.la
-LTLIBRARY_SOURCES = perchild.c
-
-include $(top_srcdir)/build/ltlib.mk
diff --git a/server/mpm/perchild/config5.m4 b/server/mpm/perchild/config5.m4
deleted file mode 100644
index bd179baed9..0000000000
--- a/server/mpm/perchild/config5.m4
+++ /dev/null
@@ -1,6 +0,0 @@
-dnl ## XXX - Need a more thorough check of the proper flags to use
-
-if test "$MPM_NAME" = "perchild" ; then
-
- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
-fi
diff --git a/server/mpm/perchild/mpm.h b/server/mpm/perchild/mpm.h
deleted file mode 100644
index d24f8b4aba..0000000000
--- a/server/mpm/perchild/mpm.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "httpd.h"
-#include "mpm_default.h"
-#include "unixd.h"
-
-#ifndef APACHE_MPM_PERCHILD_H
-#define APACHE_MPM_PERCHILD_H
-
-#define PERCHILD_MPM
-
-#define MPM_NAME "Perchild"
-
-#define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
-#define MPM_SYNC_CHILD_TABLE()
-#define MPM_CHILD_PID(i) (ap_child_table[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-
-/* Table of child status */
-#define SERVER_DEAD 0
-#define SERVER_DYING 1
-#define SERVER_ALIVE 2
-
-typedef struct ap_ctable{
- pid_t pid;
- unsigned char status;
-} ap_ctable;
-
-extern int ap_threads_per_child;
-extern int ap_max_daemons_limit;
-extern ap_ctable ap_child_table[HARD_SERVER_LIMIT];
-extern server_rec *ap_server_conf;
-extern char ap_coredump_dir[MAX_STRING_LEN];
-
-#endif /* APACHE_MPM_PERCHILD_H */
diff --git a/server/mpm/perchild/mpm_default.h b/server/mpm/perchild/mpm_default.h
deleted file mode 100644
index f462ea8f90..0000000000
--- a/server/mpm/perchild/mpm_default.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-#define AP_ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t)
-#define AP_CHILD_THREAD_FROM_ID(i) (i / HARD_THREAD_LIMIT), (i % HARD_THREAD_LIMIT)
-
-/* Number of threads to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_THREAD
-#define DEFAULT_START_THREAD 5
-#endif
-
-/* Maximum number of *free* server threads --- more than this, and
- * they will die off.
- */
-
-#ifndef DEFAULT_MAX_SPARE_THREAD
-#define DEFAULT_MAX_SPARE_THREAD 10
-#endif
-
-/* Minimum --- fewer than this, and more will be created */
-
-#ifndef DEFAULT_MIN_SPARE_THREAD
-#define DEFAULT_MIN_SPARE_THREAD 5
-#endif
-
-/* Limit on the threads per process. Clients will be locked out if more than
- * this * HARD_SERVER_LIMIT are needed.
- *
- * We keep this for one reason it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 64
-#endif
-
-/* Number of servers to spawn off by default
- */
-#ifndef DEFAULT_NUM_DAEMON
-#define DEFAULT_NUM_DAEMON 2
-#endif
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_SERVER_LIMIT
-#define HARD_SERVER_LIMIT 8
-#endif
-
-/* File used for accept locking, when we use a file */
-#ifndef DEFAULT_LOCKFILE
-#define DEFAULT_LOCKFILE "logs/accept.lock"
-#endif
-
-/* Scoreboard file, if there is one */
-#ifndef DEFAULT_SCOREBOARD
-#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
-#endif
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/perchild/perchild.c b/server/mpm/perchild/perchild.c
deleted file mode 100644
index 0fa14997b1..0000000000
--- a/server/mpm/perchild/perchild.c
+++ /dev/null
@@ -1,1829 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_hash.h"
-#include "apr_strings.h"
-#include "apr_pools.h"
-#include "apr_portable.h"
-#include "apr_file_io.h"
-#include "apr_signal.h"
-
-#define APR_WANT_IOVEC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#if !APR_HAS_THREADS
-#error The perchild MPM requires APR threads, but they are unavailable.
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h" /* for read_config */
-#include "http_core.h" /* for get_remote_host */
-#include "http_protocol.h"
-#include "http_connection.h"
-#include "ap_mpm.h"
-#include "unixd.h"
-#include "mpm_common.h"
-#include "ap_listen.h"
-#include "mpm_default.h"
-#include "mpm.h"
-#include "scoreboard.h"
-#include "util_filter.h"
-
-/* ### should be APR-ized */
-#include <poll.h>
-#include <grp.h>
-#include <pwd.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <setjmp.h>
-
-/*
- * Actual definitions of config globals
- */
-
-static int threads_to_start = 0; /* Worker threads per child */
-static int min_spare_threads = 0;
-static int max_spare_threads = 0;
-static int max_threads = 0;
-static int max_requests_per_child = 0;
-static const char *ap_pid_fname=NULL;
-static int num_daemons=0;
-static int curr_child_num=0;
-static int workers_may_exit = 0;
-static int requests_this_child;
-static int num_listenfds = 0;
-static apr_socket_t **listenfds;
-static jmp_buf jmpbuffer;
-
-struct child_info_t {
- uid_t uid;
- gid_t gid;
- int sd;
-};
-
-typedef struct {
- const char *sockname; /* The base name for the socket */
- const char *fullsockname; /* socket base name + extension */
- int sd; /* The socket descriptor */
- int sd2; /* The socket descriptor */
-} perchild_server_conf;
-
-typedef struct child_info_t child_info_t;
-
-/* Tables used to determine the user and group each child process should
- * run as. The hash table is used to correlate a server name with a child
- * process.
- */
-static child_info_t child_info_table[HARD_SERVER_LIMIT];
-static int thread_socket_table[HARD_THREAD_LIMIT];
-
-
-struct ap_ctable ap_child_table[HARD_SERVER_LIMIT];
-
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with NumServers changes across SIGWINCH restarts. We use this
- * value to optimize routines that have to scan the entire child table.
- *
- * XXX - It might not be worth keeping this code in. There aren't very
- * many child processes in this MPM.
- */
-int ap_max_daemons_limit = -1;
-int ap_threads_per_child = HARD_THREAD_LIMIT;
-
-char ap_coredump_dir[MAX_STRING_LEN];
-
-module AP_MODULE_DECLARE_DATA mpm_perchild_module;
-
-static apr_file_t *pipe_of_death_in = NULL;
-static apr_file_t *pipe_of_death_out = NULL;
-static apr_lock_t *pipe_of_death_mutex;
-
-/* *Non*-shared http_main globals... */
-
-server_rec *ap_server_conf;
-
-/* one_process --- debugging mode variable; can be set from the command line
- * with the -X flag. If set, this gets you the child_main loop running
- * in the process which originally started up (no detach, no make_child),
- * which is a pretty nice debugging environment. (You'll get a SIGHUP
- * early in standalone_main; just continue through. This is the server
- * trying to kill off any child processes which it might have lying
- * around --- Apache doesn't keep track of their pids, it just sends
- * SIGHUP to the process group, ignoring it in the root process.
- * Continue through and you'll be fine.).
- */
-
-static int one_process = 0;
-
-#ifdef DEBUG_SIGSTOP
-int raise_sigstop_flags;
-#endif
-
-static apr_pool_t *pconf; /* Pool for config stuff */
-static apr_pool_t *pchild; /* Pool for httpd child stuff */
-static apr_pool_t *thread_pool_parent; /* Parent of per-thread pools */
-static apr_lock_t *thread_pool_parent_mutex;
-
-static int child_num;
-static unsigned int my_pid; /* Linux getpid() doesn't work except in
- main thread. Use this instead */
-/* Keep track of the number of worker threads currently active */
-static int worker_thread_count;
-static apr_lock_t *worker_thread_count_mutex;
-static int worker_thread_free_ids[HARD_THREAD_LIMIT];
-static apr_threadattr_t *worker_thread_attr;
-
-/* Keep track of the number of idle worker threads */
-static int idle_thread_count;
-static apr_lock_t *idle_thread_count_mutex;
-
-/* Locks for accept serialization */
-#ifdef NO_SERIALIZED_ACCEPT
-#define SAFE_ACCEPT(stmt) APR_SUCCESS
-#else
-#define SAFE_ACCEPT(stmt) (stmt)
-static apr_lock_t *process_accept_mutex;
-#endif /* NO_SERIALIZED_ACCEPT */
-static const char *lock_fname;
-static apr_lock_t *thread_accept_mutex;
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = ap_max_daemons_limit;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_DYNAMIC;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_STATIC;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = max_threads;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-/* a clean exit from a child with proper cleanup */
-static void clean_child_exit(int code)
-{
- if (pchild) {
- apr_pool_destroy(pchild);
- }
- exit(code);
-}
-
-/* handle all varieties of core dumping signals */
-static void sig_coredump(int sig)
-{
- chdir(ap_coredump_dir);
- apr_signal(sig, SIG_DFL);
- kill(getpid(), sig);
- /* At this point we've got sig blocked, because we're still inside
- * the signal handler. When we leave the signal handler it will
- * be unblocked, and we'll take the signal... and coredump or whatever
- * is appropriate for this particular Unix. In addition the parent
- * will see the real signal we received -- whereas if we called
- * abort() here, the parent would only see SIGABRT.
- */
-}
-
-static void just_die(int sig)
-{
- clean_child_exit(0);
-}
-
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-/* we don't currently track ap_my_generation, but mod_status
- * references it so it must be defined */
-ap_generation_t volatile ap_my_generation=0;
-
-/*
- * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
- * functions to initiate shutdown or restart without relying on signals.
- * Previously this was initiated in sig_term() and restart() signal handlers,
- * but we want to be able to start a shutdown/restart from other sources --
- * e.g. on Win32, from the service manager. Now the service manager can
- * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
- * these functions can also be called by the child processes, since global
- * variables are no longer used to pass on the required action to the parent.
- *
- * These should only be called from the parent process itself, since the
- * parent process will use the shutdown_pending and restart_pending variables
- * to determine whether to shutdown or restart. The child process should
- * call signal_parent() directly to tell the parent to die -- this will
- * cause neither of those variable to be set, which the parent will
- * assume means something serious is wrong (which it will be, for the
- * child to force an exit) and so do an exit anyway.
- */
-
-static void ap_start_shutdown(void)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-/* do a graceful restart if graceful == 1 */
-static void ap_start_restart(int graceful)
-{
-
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- is_graceful = graceful;
- if (is_graceful) {
- apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
- }
-}
-
-static void sig_term(int sig)
-{
- ap_start_shutdown();
-}
-
-static void restart(int sig)
-{
-#ifndef WIN32
- ap_start_restart(sig == SIGWINCH);
-#else
- ap_start_restart(1);
-#endif
-}
-
-static void set_signals(void)
-{
-#ifndef NO_USE_SIGACTION
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
- if (!one_process) {
- sa.sa_handler = sig_coredump;
-#if defined(SA_ONESHOT)
- sa.sa_flags = SA_ONESHOT;
-#elif defined(SA_RESETHAND)
- sa.sa_flags = SA_RESETHAND;
-#endif
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
-#ifdef SIGBUS
- if (sigaction(SIGBUS, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
-#endif
-#ifdef SIGABORT
- if (sigaction(SIGABORT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
-#endif
-#ifdef SIGABRT
- if (sigaction(SIGABRT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
-#endif
-#ifdef SIGILL
- if (sigaction(SIGILL, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
-#endif
- sa.sa_flags = 0;
- }
- sa.sa_handler = sig_term;
- if (sigaction(SIGTERM, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
-#ifdef SIGINT
- if (sigaction(SIGINT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
-#endif
-#ifdef SIGXCPU
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXCPU, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
-#endif
-#ifdef SIGXFSZ
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXFSZ, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
-#endif
-#ifdef SIGPIPE
- sa.sa_handler = SIG_IGN;
- if (sigaction(SIGPIPE, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
-#endif
-
- /* we want to ignore HUPs and WINCH while we're busy processing one */
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sa.sa_handler = restart;
- if (sigaction(SIGHUP, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
- if (sigaction(SIGWINCH, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
-#else
- if (!one_process) {
- apr_signal(SIGSEGV, sig_coredump);
-#ifdef SIGBUS
- apr_signal(SIGBUS, sig_coredump);
-#endif /* SIGBUS */
-#ifdef SIGABORT
- apr_signal(SIGABORT, sig_coredump);
-#endif /* SIGABORT */
-#ifdef SIGABRT
- apr_signal(SIGABRT, sig_coredump);
-#endif /* SIGABRT */
-#ifdef SIGILL
- apr_signal(SIGILL, sig_coredump);
-#endif /* SIGILL */
-#ifdef SIGXCPU
- apr_signal(SIGXCPU, SIG_DFL);
-#endif /* SIGXCPU */
-#ifdef SIGXFSZ
- apr_signal(SIGXFSZ, SIG_DFL);
-#endif /* SIGXFSZ */
- }
-
- apr_signal(SIGTERM, sig_term);
-#ifdef SIGHUP
- apr_signal(SIGHUP, restart);
-#endif /* SIGHUP */
-#ifdef SIGWINCH
- apr_signal(SIGWINCH, restart);
-#endif /* SIGWINCH */
-#ifdef SIGPIPE
- apr_signal(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
-
-#endif
-}
-
-/*****************************************************************
- * Here follows a long bunch of generic server bookkeeping stuff...
- */
-
-int ap_graceful_stop_signalled(void)
-{
- /* XXX - Does this really work? - Manoj */
- return is_graceful;
-}
-
-/*****************************************************************
- * Child process main loop.
- */
-
-static void process_socket(apr_pool_t *p, apr_socket_t *sock, long conn_id)
-{
- conn_rec *current_conn;
- int csd;
- apr_status_t rv;
- int thread_num = conn_id % HARD_THREAD_LIMIT;
-
- if ((rv = apr_os_sock_get(&csd, sock)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "apr_os_sock_get");
- }
-
- if (csd >= FD_SETSIZE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
- "new file descriptor %d is too large; you probably need "
- "to rebuild Apache with a larger FD_SETSIZE "
- "(currently %d)",
- csd, FD_SETSIZE);
- apr_socket_close(sock);
- return;
- }
-
- if (thread_socket_table[thread_num] < 0) {
- ap_sock_disable_nagle(sock);
- }
-
- current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id);
- if (current_conn) {
- ap_process_connection(current_conn);
- ap_lingering_close(current_conn);
- }
-}
-
-static void *worker_thread(void *);
-
-/* Starts a thread as long as we're below max_threads */
-static int start_thread(void)
-{
- apr_thread_t *thread;
- int rc;
-
- apr_lock_acquire(worker_thread_count_mutex);
- if (worker_thread_count < max_threads - 1) {
- if ((rc = apr_thread_create(&thread, worker_thread_attr, worker_thread,
- &worker_thread_free_ids[worker_thread_count], pchild))) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, rc, ap_server_conf,
- "apr_thread_create: unable to create worker thread");
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again if we exit. */
- sleep(10);
- workers_may_exit = 1;
- apr_lock_release(worker_thread_count_mutex);
- return 0;
- }
- else {
- worker_thread_count++;
- }
- }
- else {
- static int reported = 0;
-
- if (!reported) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
- "server reached MaxThreadsPerChild setting, consider raising the"
- " MaxThreadsPerChild or NumServers settings");
- reported = 1;
- }
- apr_lock_release(worker_thread_count_mutex);
- return 0;
- }
- apr_lock_release(worker_thread_count_mutex);
- return 1;
-
-}
-/* Sets workers_may_exit if we received a character on the pipe_of_death */
-static void check_pipe_of_death(void)
-{
- apr_lock_acquire(pipe_of_death_mutex);
- if (!workers_may_exit) {
- int ret;
- char pipe_read_char;
- apr_size_t n = 1;
-
- ret = apr_recv(listenfds[0], &pipe_read_char, &n);
- if (APR_STATUS_IS_EAGAIN(ret)) {
- /* It lost the lottery. It must continue to suffer
- * through a life of servitude. */
- }
- else {
- /* It won the lottery (or something else is very
- * wrong). Embrace death with open arms. */
- workers_may_exit = 1;
- }
- }
- apr_lock_release(pipe_of_death_mutex);
-}
-
-/* idle_thread_count should be incremented before starting a worker_thread */
-
-static void *worker_thread(void *arg)
-{
- apr_socket_t *csd = NULL;
- apr_pool_t *tpool; /* Pool for this thread */
- apr_pool_t *ptrans; /* Pool for per-transaction stuff */
- apr_socket_t *sd = NULL;
- int srv;
- int curr_pollfd, last_pollfd = 0;
- int thread_just_started = 1;
- int thread_num = *((int *) arg);
- long conn_id = child_num * HARD_THREAD_LIMIT + thread_num;
- apr_pollfd_t *pollset;
- int n;
- apr_status_t rv;
-
- apr_lock_acquire(thread_pool_parent_mutex);
- apr_pool_create(&tpool, thread_pool_parent);
- apr_lock_release(thread_pool_parent_mutex);
- apr_pool_create(&ptrans, tpool);
-
- (void) ap_update_child_status(child_num, thread_num, SERVER_STARTING,
- (request_rec *) NULL);
-
- apr_poll_setup(&pollset, num_listenfds+1, tpool);
- for(n=0 ; n <= num_listenfds ; ++n) {
- apr_poll_socket_add(pollset, listenfds[n], APR_POLLIN);
- }
-
- while (!workers_may_exit) {
- workers_may_exit |= (max_requests_per_child != 0) && (requests_this_child <= 0);
- if (workers_may_exit) break;
- if (!thread_just_started) {
- apr_lock_acquire(idle_thread_count_mutex);
- if (idle_thread_count < max_spare_threads) {
- idle_thread_count++;
- apr_lock_release(idle_thread_count_mutex);
- }
- else {
- apr_lock_release(idle_thread_count_mutex);
- break;
- }
- }
- else {
- thread_just_started = 0;
- }
-
- (void) ap_update_child_status(child_num, thread_num, SERVER_READY,
- (request_rec *) NULL);
-
- apr_lock_acquire(thread_accept_mutex);
- if (workers_may_exit) {
- apr_lock_release(thread_accept_mutex);
- break;
- }
- if ((rv = SAFE_ACCEPT(apr_lock_acquire(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_acquire failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
-
- while (!workers_may_exit) {
- apr_int16_t event;
- srv = apr_poll(pollset, &n, -1);
-
- if (srv != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(srv)) {
- continue;
- }
-
- /* apr_poll() will only return errors in catastrophic
- * circumstances. Let's try exiting gracefully, for now. */
- ap_log_error(APLOG_MARK, APLOG_ERR, srv, (const server_rec *)
- ap_server_conf, "apr_poll: (listen)");
- workers_may_exit = 1;
- }
- if (workers_may_exit) break;
-
- apr_poll_revents_get(&event, listenfds[0], pollset);
- if (event & APR_POLLIN) {
- /* A process got a signal on the shutdown pipe. Check if we're
- * the lucky process to die. */
- check_pipe_of_death();
- continue;
- }
-
- apr_poll_revents_get(&event, listenfds[1], pollset);
- if (event & APR_POLLIN || event & APR_POLLOUT) {
- /* This request is from another child in our current process.
- * We should set a flag here, and then below we will read
- * two bytes (the socket number and the NULL byte.
- */
- thread_socket_table[thread_num] = -2;
- goto got_from_other_child;
- }
-
- if (num_listenfds == 1) {
- sd = ap_listeners->sd;
- goto got_fd;
- }
- else {
- /* find a listener */
- curr_pollfd = last_pollfd;
- do {
- curr_pollfd++;
- if (curr_pollfd > num_listenfds) {
- curr_pollfd = 1;
- }
- /* XXX: Should we check for POLLERR? */
- apr_poll_revents_get(&event, listenfds[curr_pollfd], pollset);
- if (event & APR_POLLIN) {
- last_pollfd = curr_pollfd;
- sd = listenfds[curr_pollfd];
- goto got_fd;
- }
- } while (curr_pollfd != last_pollfd);
- }
- }
- got_fd:
- if (!workers_may_exit) {
- if ((rv = apr_accept(&csd, sd, ptrans)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "apr_accept");
- }
- if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- apr_lock_release(thread_accept_mutex);
- apr_lock_acquire(idle_thread_count_mutex);
- if (idle_thread_count > min_spare_threads) {
- idle_thread_count--;
- }
- else {
- if (!start_thread()) {
- idle_thread_count--;
- }
- }
- apr_lock_release(idle_thread_count_mutex);
- got_from_other_child:
- if (thread_socket_table[thread_num] == -2) {
- struct msghdr msg;
- struct cmsghdr *cmsg;
- char sockname[80];
- struct iovec iov;
- int ret, sd, dp;
-
- iov.iov_base = sockname;
- iov.iov_len = 80;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- cmsg = apr_palloc(ptrans, sizeof(*cmsg) + sizeof(sd));
- cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sd);
- msg.msg_control = (caddr_t)cmsg;
- msg.msg_controllen = cmsg->cmsg_len;
- msg.msg_flags = 0;
-
- ret = recvmsg(child_info_table[child_num].sd, &msg, 0);
-
- memcpy(&dp, CMSG_DATA(cmsg), sizeof(dp));
-
- thread_socket_table[thread_num] = dp;
- apr_os_sock_put(&csd, &child_info_table[child_num].sd, ptrans);
- }
- if (setjmp(jmpbuffer) != 1) {
- process_socket(ptrans, csd, conn_id);
- }
- else {
- thread_socket_table[thread_num] = -1;
- }
- requests_this_child--;
- } else {
- if ((rv = SAFE_ACCEPT(apr_lock_release(process_accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- apr_lock_release(thread_accept_mutex);
- apr_lock_acquire(idle_thread_count_mutex);
- idle_thread_count--;
- apr_lock_release(idle_thread_count_mutex);
- break;
- }
- apr_pool_clear(ptrans);
- }
-
- apr_lock_acquire(thread_pool_parent_mutex);
- ap_update_child_status(child_num, thread_num, SERVER_DEAD,
- (request_rec *) NULL);
- apr_pool_destroy(tpool);
- apr_lock_release(thread_pool_parent_mutex);
- apr_lock_acquire(worker_thread_count_mutex);
- worker_thread_count--;
- worker_thread_free_ids[worker_thread_count] = thread_num;
- if (worker_thread_count == 0) {
- /* All the threads have exited, now finish the shutdown process
- * by signalling the sigwait thread */
- kill(my_pid, SIGTERM);
- }
- apr_lock_release(worker_thread_count_mutex);
-
- return NULL;
-}
-
-/* Set group privileges.
- *
- * Note that we use the username as set in the config files, rather than
- * the lookup of to uid --- the same uid may have multiple passwd entries,
- * with different sets of groups for each.
- */
-
-static int set_group_privs(uid_t uid, gid_t gid)
-{
- if (!geteuid()) {
- const char *name;
-
- /* Get username if passed as a uid */
-
- struct passwd *ent;
-
- if ((ent = getpwuid(uid)) == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "getpwuid: couldn't determine user name from uid %u, "
- "you probably need to modify the User directive",
- (unsigned)uid);
- return -1;
- }
-
- name = ent->pw_name;
-
- /*
- * Set the GID before initgroups(), since on some platforms
- * setgid() is known to zap the group list.
- */
- if (setgid(gid) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "setgid: unable to set group id to Group %u",
- (unsigned)gid);
- return -1;
- }
-
- /* Reset `groups' attributes. */
-
- if (initgroups(name, gid) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "initgroups: unable to set groups for User %s "
- "and Group %u", name, (unsigned)gid);
- return -1;
- }
- }
- return 0;
-}
-
-
-static int perchild_setup_child(int childnum)
-{
- child_info_t *ug = &child_info_table[childnum];
-
- if (ug->uid == -1 && ug->gid == -1) {
- return unixd_setup_child();
- }
- if (set_group_privs(ug->uid, ug->gid)) {
- return -1;
- }
- /* Only try to switch if we're running as root */
- if (!geteuid() && (
-#ifdef _OSD_POSIX
- os_init_job_environment(server_conf, unixd_config.user_name, one_process) != 0 ||
-#endif
- setuid(ug->uid) == -1)) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
- "setuid: unable to change to uid: %ld",
- (long) ug->uid);
- return -1;
- }
- return 0;
-}
-
-static int check_signal(int signum)
-{
- switch (signum) {
- case SIGTERM:
- case SIGINT:
- just_die(signum);
- return 1;
- }
- return 0;
-}
-
-static void child_main(int child_num_arg)
-{
- int i;
- ap_listen_rec *lr;
- apr_status_t rv;
- apr_thread_t *thread;
-
- my_pid = getpid();
- child_num = child_num_arg;
- apr_pool_create(&pchild, pconf);
-
- /*stuff to do before we switch id's, so we have permissions.*/
-
- rv = SAFE_ACCEPT(apr_lock_child_init(&process_accept_mutex, lock_fname,
- pchild));
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "Couldn't initialize cross-process lock in child");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- if (perchild_setup_child(child_num)) {
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- ap_run_child_init(pchild, ap_server_conf);
-
- /*done with init critical section */
-
- apr_setup_signal_thread();
-
- requests_this_child = max_requests_per_child;
-
- /* Set up the pollfd array, num_listenfds + 1 for the pipe and 1 for
- * the child socket.
- */
- listenfds = apr_pcalloc(pchild, sizeof(*listenfds) * (num_listenfds + 2));
-#if APR_FILES_AS_SOCKETS
- apr_socket_from_file(&listenfds[0], pipe_of_death_in);
-#endif
-
- /* The child socket */
- apr_os_sock_put(&listenfds[1], &child_info_table[child_num].sd, pchild);
-
- num_listenfds++;
- for (lr = ap_listeners, i = 2; i <= num_listenfds; lr = lr->next, ++i)
- listenfds[i]=lr->sd;
-
- /* Setup worker threads */
-
- if (threads_to_start > max_threads) {
- threads_to_start = max_threads;
- }
- idle_thread_count = threads_to_start;
- worker_thread_count = 0;
- for (i = 0; i < max_threads; i++) {
- worker_thread_free_ids[i] = i;
- }
- apr_pool_create(&thread_pool_parent, pchild);
- apr_lock_create(&thread_pool_parent_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&idle_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&pipe_of_death_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&thread_accept_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
-
- apr_threadattr_create(&worker_thread_attr, pchild);
- apr_threadattr_detach_set(worker_thread_attr, 1);
-
- /* We are creating worker threads right now */
- for (i=0; i < threads_to_start; i++) {
- /* start_thread shouldn't fail here */
- if (!start_thread()) {
- break;
- }
- }
-
- apr_signal_thread(check_signal);
-}
-
-static int make_child(server_rec *s, int slot)
-{
- int pid;
-
- if (slot + 1 > ap_max_daemons_limit) {
- ap_max_daemons_limit = slot + 1;
- }
-
- if (one_process) {
- set_signals();
- ap_child_table[slot].pid = getpid();
- ap_child_table[slot].status = SERVER_ALIVE;
- child_main(slot);
- }
- (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
-
- if ((pid = fork()) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
- "fork: Unable to fork new process");
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again. */
- sleep(10);
-
- return -1;
- }
-
- if (!pid) {
-#ifdef AIX_BIND_PROCESSOR
- /* By default, AIX binds to a single processor. This bit unbinds
- children which will then bind to another CPU.
- */
-#include <sys/processor.h>
- int status = bindprocessor(BINDPROCESS, (int)getpid(),
- PROCESSOR_CLASS_ANY);
- if (status != OK)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno,
- ap_server_conf, "processor unbind failed %d", status);
-#endif
-
- RAISE_SIGSTOP(MAKE_CHILD);
-
- /* XXX - For an unthreaded server, a signal handler will be necessary
- apr_signal(SIGTERM, just_die);
- */
- child_main(slot);
- clean_child_exit(0);
- }
- /* else */
- ap_child_table[slot].pid = pid;
- ap_child_table[slot].status = SERVER_ALIVE;
-
- return 0;
-}
-
-/* start up a bunch of children */
-static int startup_children(int number_to_start)
-{
- int i;
-
- for (i = 0; number_to_start && i < num_daemons; ++i) {
- if (ap_child_table[i].pid) {
- continue;
- }
- if (make_child(ap_server_conf, i) < 0) {
- break;
- }
- --number_to_start;
- }
- return number_to_start;
-}
-
-
-/*
- * spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
-static void perform_child_maintenance(void)
-{
- int i;
- int free_length;
- int free_slots[MAX_SPAWN_RATE];
- int last_non_dead = -1;
-
- /* initialize the free_list */
- free_length = 0;
-
- for (i = 0; i < num_daemons; ++i) {
- if (ap_child_table[i].pid == 0) {
- if (free_length < spawn_rate) {
- free_slots[free_length] = i;
- ++free_length;
- }
- }
- else {
- last_non_dead = i;
- }
-
- if (i >= ap_max_daemons_limit && free_length >= spawn_rate) {
- break;
- }
- }
- ap_max_daemons_limit = last_non_dead + 1;
-
- if (free_length > 0) {
- for (i = 0; i < free_length; ++i) {
- make_child(ap_server_conf, free_slots[i]);
- }
- /* the next time around we want to spawn twice as many if this
- * wasn't good enough, but not if we've just done a graceful
- */
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
- }
- else if (spawn_rate < MAX_SPAWN_RATE) {
- spawn_rate *= 2;
- }
- }
- else {
- spawn_rate = 1;
- }
-}
-
-static void server_main_loop(int remaining_children_to_start)
-{
- int child_slot;
- apr_wait_t status;
- apr_proc_t pid;
- int i;
-
- while (!restart_pending && !shutdown_pending) {
- ap_wait_or_timeout(&status, &pid, pconf);
-
- if (pid.pid != -1) {
- ap_process_child_status(&pid, status);
- /* non-fatal death... note that it's gone in the child table and
- * clean out the status table. */
- child_slot = -1;
- for (i = 0; i < ap_max_daemons_limit; ++i) {
- if (ap_child_table[i].pid == pid.pid) {
- child_slot = i;
- break;
- }
- }
- if (child_slot >= 0) {
- ap_child_table[child_slot].pid = 0;
- ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
-
-
- if (remaining_children_to_start
- && child_slot < num_daemons) {
- /* we're still doing a 1-for-1 replacement of dead
- * children with new children
- */
- make_child(ap_server_conf, child_slot);
- --remaining_children_to_start;
- }
-#if APR_HAS_OTHER_CHILD
- }
- else if (apr_proc_other_child_read(&pid, status) == 0) {
- /* handled */
-#endif
- }
- else if (is_graceful) {
- /* Great, we've probably just lost a slot in the
- * child table. Somehow we don't know about this
- * child.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0,
- ap_server_conf,
- "long lost child came home! (pid %ld)",
- (long)pid.pid);
- }
- /* Don't perform idle maintenance when a child dies,
- * only do it when there's a timeout. Remember only a
- * finite number of children can die, and it's pretty
- * pathological for a lot to die suddenly.
- */
- continue;
- }
- else if (remaining_children_to_start) {
- /* we hit a 1 second timeout in which none of the previous
- * generation of children needed to be reaped... so assume
- * they're all done, and pick up the slack if any is left.
- */
- remaining_children_to_start = \
- startup_children(remaining_children_to_start);
- /* In any event we really shouldn't do the code below because
- * few of the servers we just started are in the IDLE state
- * yet, so we'd mistakenly create an extra server.
- */
- continue;
- }
-
- perform_child_maintenance();
- }
-}
-
-int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
-{
- int remaining_children_to_start;
- int i;
- apr_status_t rv;
- apr_size_t one = 1;
-
- pconf = _pconf;
- ap_server_conf = s;
- if ((rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out, pconf))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_create (pipe_of_death)");
- exit(1);
- }
- if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_timeout_set (pipe_of_death)");
- exit(1);
- }
- ap_server_conf = s;
- if ((num_listenfds = ap_setup_listeners(ap_server_conf)) < 1) {
- /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
- "no listening sockets available, shutting down");
- return 1;
- }
- ap_log_pid(pconf, ap_pid_fname);
-
- /* Initialize cross-process accept lock */
- lock_fname = apr_psprintf(_pconf, "%s.%u",
- ap_server_root_relative(_pconf, lock_fname),
- my_pid);
- rv = SAFE_ACCEPT(apr_lock_create(&process_accept_mutex, APR_MUTEX,
- APR_CROSS_PROCESS, lock_fname, _pconf));
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
- "Couldn't create cross-process lock");
- return 1;
- }
-
- if (!is_graceful) {
- ap_create_scoreboard(pconf, SB_SHARED);
- }
- /* Initialize the child table */
- if (!is_graceful) {
- for (i = 0; i < HARD_SERVER_LIMIT; i++) {
- ap_child_table[i].pid = 0;
- }
- }
-
- set_signals();
-
- /* If we're doing a graceful_restart then we're going to see a lot
- * of children exiting immediately when we get into the main loop
- * below (because we just sent them SIGWINCH). This happens pretty
- * rapidly... and for each one that exits we'll start a new one until
- * we reach at least daemons_min_free. But we may be permitted to
- * start more than that, so we'll just keep track of how many we're
- * supposed to start up without the 1 second penalty between each fork.
- */
- remaining_children_to_start = num_daemons;
- if (!is_graceful) {
- remaining_children_to_start = \
- startup_children(remaining_children_to_start);
- }
- else {
- /* give the system some time to recover before kicking into
- * exponential mode */
- hold_off_on_exponential_spawning = 10;
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "%s configured -- resuming normal operations",
- ap_get_server_version());
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "Server built: %s", ap_get_server_built());
- restart_pending = shutdown_pending = 0;
-
- server_main_loop(remaining_children_to_start);
-
- if (shutdown_pending) {
- /* Time to gracefully shut down:
- * Kill child processes, tell them to call child_exit, etc...
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
- "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
-
- /* cleanup pid file on normal shutdown */
- {
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
- ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
- ap_server_conf, "caught SIGTERM, shutting down");
-
- return 1;
- }
-
- /* we've been told to restart */
- apr_signal(SIGHUP, SIG_IGN);
-
- if (one_process) {
- /* not worth thinking about */
- return 1;
- }
-
- if (is_graceful) {
- char char_of_death = '!';
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGWINCH received. Doing graceful restart");
-
- /* This is mostly for debugging... so that we know what is still
- * gracefully dealing with existing request.
- */
-
- for (i = 0; i < num_daemons; ++i) {
- if (ap_child_table[i].pid) {
- ap_child_table[i].status = SERVER_DYING;
- }
- }
- /* give the children the signal to die */
- for (i = 0; i < num_daemons;) {
- if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(rv)) continue;
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
- "write pipe_of_death");
- }
- i++;
- }
- }
- else {
- /* Kill 'em all. Since the child acts the same on the parents SIGTERM
- * and a SIGHUP, we may as well use the same signal, because some user
- * pthreads are stealing signals from us left and right.
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
- "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
- ap_server_conf, "SIGHUP received. Attempting to restart");
- }
- return 0;
-}
-
-static void perchild_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- static int restart_num = 0;
- int no_detach = 0;
- int i;
-
- one_process = !!ap_exists_config_define("ONE_PROCESS");
- no_detach = !!ap_exists_config_define("NO_DETACH");
-
- /* sigh, want this only the second time around */
- if (restart_num++ == 1) {
- is_graceful = 0;
-
- if (!one_process && !no_detach) {
- apr_proc_detach();
- }
-
- my_pid = getpid();
- }
-
- unixd_pre_config(ptemp);
- ap_listen_pre_config();
- num_daemons = DEFAULT_NUM_DAEMON;
- threads_to_start = DEFAULT_START_THREAD;
- min_spare_threads = DEFAULT_MIN_SPARE_THREAD;
- max_spare_threads = DEFAULT_MAX_SPARE_THREAD;
- max_threads = HARD_THREAD_LIMIT;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_scoreboard_fname = DEFAULT_SCOREBOARD;
- lock_fname = DEFAULT_LOCKFILE;
- max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
- curr_child_num = 0;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-
- for (i = 0; i < HARD_SERVER_LIMIT; i++) {
- child_info_table[i].uid = -1;
- child_info_table[i].gid = -1;
- child_info_table[i].sd = -1;
- }
- for (i = 0; i < HARD_THREAD_LIMIT; i++) {
- thread_socket_table[i] = -1;
- }
-}
-
-static int pass_request(request_rec *r)
-{
- apr_socket_t *thesock = r->connection->client_socket;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- int sfd;
- struct iovec iov;
- apr_bucket_brigade *bb = apr_brigade_create(r->pool);
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(r->server->module_config,
- &mpm_perchild_module);
- char *foo;
- apr_size_t len;
- apr_size_t readbytes = 0;
-
- apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool);
- len = strlen(foo);
-
- apr_pool_userdata_set(NULL, "PERCHILD_BUFFER", apr_pool_cleanup_null,
- r->connection->pool);
-
- apr_os_sock_get(&sfd, thesock);
-
- iov.iov_base = NULL;
- iov.iov_len = 0;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd));
- cmsg->cmsg_len = sizeof(*cmsg) + sizeof(int);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
-
- memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd));
-
- msg.msg_control = (caddr_t)cmsg;
- msg.msg_controllen = cmsg->cmsg_len;
- msg.msg_flags=0;
-
- if (sendmsg(sconf->sd2, &msg, 0) == -1) {
- apr_pool_destroy(r->pool);
- return -1;
- }
-
- write(sconf->sd2, foo, len);
-
- while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING, &readbytes) == APR_SUCCESS) {
- apr_bucket *e;
- APR_BRIGADE_FOREACH(e, bb) {
- const char *str;
-
- apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
- write(sconf->sd2, str, len);
- }
- }
-
- apr_pool_destroy(r->pool);
- return 1;
-}
-
-static char *make_perchild_socket(const char *fullsockname, int sd[2])
-{
- socketpair(PF_UNIX, SOCK_STREAM, 0, sd);
- return NULL;
-}
-
-
-static void perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
-{
- int i;
- server_rec *sr;
- perchild_server_conf *sconf;
- int def_sd[2];
-
- def_sd[0] = -1;
- def_sd[1] = -1;
-
- for (sr = s; sr; sr = sr->next) {
- sconf = (perchild_server_conf *)ap_get_module_config(sr->module_config,
- &mpm_perchild_module);
-
- if (sconf->sd == -1) {
- sconf->fullsockname = apr_pstrcat(sr->process->pool,
- sconf->sockname, ".DEFAULT", NULL);
- if (def_sd[0] == -1) {
- if (!make_perchild_socket(sconf->fullsockname, def_sd)) {
- /* log error */
- }
- }
- sconf->sd = def_sd[0];
- sconf->sd2 = def_sd[1];
- }
- }
-
- for (i = 0; i < num_daemons; i++) {
- if (child_info_table[i].uid == -1) {
- child_info_table[i].sd = def_sd[0];
- }
- }
-}
-
-static int perchild_post_read(request_rec *r)
-{
- ap_filter_t *f = r->connection->input_filters;
- int thread_num = r->connection->id % HARD_THREAD_LIMIT;
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(r->server->module_config,
- &mpm_perchild_module);
-
- while (f) {
- if (!strcmp("PERCHILD_BUFFER", f->frec->name)) {
- ap_remove_output_filter(f);
- break;
- }
- f = f->next;
- }
-
- if (thread_socket_table[thread_num] != -1) {
- apr_socket_t *csd = NULL;
-
- apr_os_sock_put(&csd, &thread_socket_table[thread_num],
- r->connection->pool);
- ap_sock_disable_nagle(csd);
- r->connection->client_socket = csd;
- return OK;
- }
- else {
- if (sconf->sd != child_info_table[child_num].sd) {
- if (pass_request(r) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0,
- ap_server_conf, "Could not pass request to proper "
- "child, request will not be honored.");
- }
- longjmp(jmpbuffer, 1);
- }
- return OK;
- }
- return OK;
-}
-
-static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_bucket *e;
- apr_status_t rv;
- char *buffer = NULL;
- const char *str;
- apr_size_t len;
-
- if ((rv = ap_get_brigade(f->next, b, mode, readbytes)) != APR_SUCCESS) {
- return rv;
- }
-
- apr_pool_userdata_get((void **)&buffer, "PERCHILD_BUFFER", f->c->pool);
-
- APR_BRIGADE_FOREACH(e, b) {
- if (e->length != 0) {
- apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
-
- if (buffer == NULL) {
- buffer = apr_pstrndup(f->c->pool, str, len);
- }
- else {
- buffer = apr_pstrcat(f->c->pool, buffer,
- apr_pstrndup(f->c->pool, str, len), NULL);
- }
- }
- }
- apr_pool_userdata_set(buffer, "PERCHILD_BUFFER", apr_pool_cleanup_null, f->c->pool);
-
- return APR_SUCCESS;
-}
-
-static int perchild_pre_connection(conn_rec *c)
-{
- ap_add_input_filter("PERCHILD_BUFFER", NULL, NULL, c);
- return OK;
-}
-
-static void perchild_hooks(apr_pool_t *p)
-{
- one_process = 0;
-
- ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_pre_connection(perchild_pre_connection,NULL,NULL, APR_HOOK_MIDDLE);
-
- /* This must be run absolutely first. If this request isn't for this
- * server then we need to forward it to the proper child. No sense
- * tying up this server running more post_read request hooks if it is
- * just going to be forwarded along.
- */
- ap_hook_post_read_request(perchild_post_read, NULL, NULL, APR_HOOK_REALLY_FIRST);
- ap_register_input_filter("PERCHILD_BUFFER", perchild_buffer, AP_FTYPE_CONTENT);
-}
-
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in <VirtualHost>";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_scoreboard_fname = arg;
- return NULL;
-}
-
-static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- lock_fname = arg;
- return NULL;
-}
-static const char *set_num_daemons (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- num_daemons = atoi(arg);
- if (num_daemons > HARD_SERVER_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: NumServers of %d exceeds compile time limit "
- "of %d servers,", num_daemons, HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering NumServers to %d. To increase, please "
- "see the", HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_SERVER_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- num_daemons = HARD_SERVER_LIMIT;
- }
- else if (num_daemons < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require NumServers > 0, setting to 1");
- num_daemons = 1;
- }
- return NULL;
-}
-
-static const char *set_threads_to_start (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- threads_to_start = atoi(arg);
- if (threads_to_start > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: StartThreads of %d exceeds compile time"
- " limit of %d threads,", threads_to_start,
- HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering StartThreads to %d. To increase, please"
- " see the", HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_THREAD_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- }
- else if (threads_to_start < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require StartThreads > 0, setting to 1");
- threads_to_start = 1;
- }
- return NULL;
-}
-
-static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- min_spare_threads = atoi(arg);
- if (min_spare_threads <= 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set to non-positive.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Resetting to 1 to avoid almost certain Apache failure.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Please read the documentation.");
- min_spare_threads = 1;
- }
-
- return NULL;
-}
-
-static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_spare_threads = atoi(arg);
- if (max_spare_threads >= HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set higher than");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
- max_spare_threads = HARD_THREAD_LIMIT;
- }
- return NULL;
-}
-
-static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_threads = atoi(arg);
- if (max_threads > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MaxThreadsPerChild set higher than");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
- max_threads = HARD_THREAD_LIMIT;
- }
- return NULL;
-}
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_requests_per_child = atoi(arg);
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-static const char *set_child_per_uid(cmd_parms *cmd, void *dummy, const char *u,
- const char *g, const char *num)
-{
- int i;
- int max_this_time = atoi(num) + curr_child_num;
- for (i = curr_child_num; i < max_this_time; i++, curr_child_num++); {
- child_info_t *ug = &child_info_table[i - 1];
-
- if (i > num_daemons) {
- return "Trying to use more child ID's than NumServers. Increase "
- "NumServers in your config file.";
- }
-
- ug->uid = atoi(u);
- ug->gid = atoi(g);
- }
- return NULL;
-}
-
-static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid,
- const char *gid)
-{
- int i;
- int u = atoi(uid);
- int g = atoi(gid);
- const char *errstr;
- int socks[2];
- perchild_server_conf *sconf = (perchild_server_conf *)
- ap_get_module_config(cmd->server->module_config,
- &mpm_perchild_module);
-
- sconf->fullsockname = apr_pstrcat(cmd->pool, sconf->sockname, ".", uid, ":", gid, NULL);
-
- if ((errstr = make_perchild_socket(sconf->fullsockname, socks))) {
- return errstr;
- }
-
- sconf->sd = socks[0];
- sconf->sd2 = socks[1];
-
- for (i = 0; i < num_daemons; i++) {
- if (u == child_info_table[i].uid && g == child_info_table[i].gid) {
- child_info_table[i].sd = sconf->sd;
- }
- }
-
- return NULL;
-}
-
-
-static const command_rec perchild_cmds[] = {
-UNIX_DAEMON_COMMANDS
-LISTEN_COMMANDS
-AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
- "A file for logging the server process ID"),
-AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
- "A file for Apache to maintain runtime process management information"),
-AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
- "The lockfile used when Apache needs to lock the accept() call"),
-AP_INIT_TAKE1("NumServers", set_num_daemons, NULL, RSRC_CONF,
- "Number of children alive at the same time"),
-AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF,
- "Number of threads each child creates"),
-AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
- "Minimum number of idle threads per child, to handle request spikes"),
-AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
- "Maximum number of idle threads per child"),
-AP_INIT_TAKE1("MaxThreadsPerChild", set_max_threads, NULL, RSRC_CONF,
- "Maximum number of threads per child"),
-AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
- "Maximum number of requests a particular child serves before dying."),
-AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
- "The location of the directory Apache changes to before dumping core"),
-AP_INIT_TAKE3("ChildperUserID", set_child_per_uid, NULL, RSRC_CONF,
- "Specify a User and Group for a specific child process."),
-AP_INIT_TAKE2("AssignUserID", assign_childuid, NULL, RSRC_CONF,
- "Tie a virtual host to a specific child process."),
-{ NULL }
-};
-
-static void *perchild_create_config(apr_pool_t *p, server_rec *s)
-{
- perchild_server_conf *c =
- (perchild_server_conf *) apr_pcalloc(p, sizeof(perchild_server_conf));
-
- c->sd = -1;
- return c;
-}
-
-module AP_MODULE_DECLARE_DATA mpm_perchild_module = {
- MPM20_MODULE_STUFF,
- NULL, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- perchild_create_config, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- perchild_cmds, /* command apr_table_t */
- perchild_hooks /* register_hooks */
-};
-
diff --git a/server/mpm/prefork/.cvsignore b/server/mpm/prefork/.cvsignore
deleted file mode 100644
index dc53ac865d..0000000000
--- a/server/mpm/prefork/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*.lo
-*.la
-Makefile
-.deps
-.libs
diff --git a/server/mpm/prefork/Makefile.in b/server/mpm/prefork/Makefile.in
deleted file mode 100644
index 034bf5ce84..0000000000
--- a/server/mpm/prefork/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-LTLIBRARY_NAME = libprefork.la
-LTLIBRARY_SOURCES = prefork.c
-
-include $(top_srcdir)/build/ltlib.mk
diff --git a/server/mpm/prefork/config.m4 b/server/mpm/prefork/config.m4
deleted file mode 100644
index 9c189a8642..0000000000
--- a/server/mpm/prefork/config.m4
+++ /dev/null
@@ -1,3 +0,0 @@
-if test "$MPM_NAME" = "prefork" ; then
- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
-fi
diff --git a/server/mpm/prefork/mpm.h b/server/mpm/prefork/mpm.h
deleted file mode 100644
index 6a923b0636..0000000000
--- a/server/mpm/prefork/mpm.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "httpd.h"
-#include "mpm_default.h"
-#include "scoreboard.h"
-#include "unixd.h"
-
-#ifndef APACHE_MPM_PREFORK_H
-#define APACHE_MPM_PREFORK_H
-
-#define PREFORK_MPM
-
-#define MPM_NAME "Prefork"
-
-#define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
-#define MPM_SYNC_CHILD_TABLE() (ap_sync_scoreboard_image())
-#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-
-extern int ap_threads_per_child;
-extern int ap_max_daemons_limit;
-extern server_rec *ap_server_conf;
-extern char ap_coredump_dir[MAX_STRING_LEN];
-#endif /* APACHE_MPM_PREFORK_H */
diff --git a/server/mpm/prefork/mpm_default.h b/server/mpm/prefork/mpm_default.h
deleted file mode 100644
index 3763037ae6..0000000000
--- a/server/mpm/prefork/mpm_default.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-#define AP_ID_FROM_CHILD_THREAD(c, t) c
-#define AP_CHILD_THREAD_FROM_ID(i) i, 0
-
-
-/* Number of servers to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_DAEMON
-#define DEFAULT_START_DAEMON 5
-#endif
-
-/* Maximum number of *free* server processes --- more than this, and
- * they will die off.
- */
-
-#ifndef DEFAULT_MAX_FREE_DAEMON
-#define DEFAULT_MAX_FREE_DAEMON 10
-#endif
-
-/* Minimum --- fewer than this, and more will be created */
-
-#ifndef DEFAULT_MIN_FREE_DAEMON
-#define DEFAULT_MIN_FREE_DAEMON 5
-#endif
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_SERVER_LIMIT
-#define HARD_SERVER_LIMIT 256
-#endif
-
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 1
-#endif
-
-/* File used for accept locking, when we use a file */
-#ifndef DEFAULT_LOCKFILE
-#define DEFAULT_LOCKFILE "logs/accept.lock"
-#endif
-
-/* Scoreboard file, if there is one */
-#ifndef DEFAULT_SCOREBOARD
-#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
-#endif
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
deleted file mode 100644
index 52ed0b51e0..0000000000
--- a/server/mpm/prefork/prefork.c
+++ /dev/null
@@ -1,1515 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * httpd.c: simple http daemon for answering WWW file requests
- *
- *
- * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
- *
- * 03-06-95 blong
- * changed server number for child-alone processes to 0 and changed name
- * of processes
- *
- * 03-10-95 blong
- * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
- * including set group before fork, and call gettime before to fork
- * to set up libraries.
- *
- * 04-14-95 rst / rh
- * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
- * Apache server, and also to have child processes do accept() directly.
- *
- * April-July '95 rst
- * Extensive rework for Apache.
- */
-
-/* TODO: this is a cobbled together prefork MPM example... it should mostly
- * TODO: behave like apache-1.3... here's a short list of things I think
- * TODO: need cleaning up still:
- */
-
-#include "apr.h"
-#include "apr_portable.h"
-#include "apr_strings.h"
-#include "apr_thread_proc.h"
-#include "apr_signal.h"
-
-#define APR_WANT_STDIO
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "mpm_default.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h"
-#include "http_core.h" /* for get_remote_host */
-#include "http_connection.h"
-#include "scoreboard.h"
-#include "ap_mpm.h"
-#include "unixd.h"
-#include "mpm_common.h"
-#include "ap_listen.h"
-#include "ap_mmn.h"
-
-#ifdef HAVE_BSTRING_H
-#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#include <signal.h>
-#include <sys/times.h>
-
-/* config globals */
-
-int ap_threads_per_child=0; /* Worker threads per child */
-static int ap_max_requests_per_child=0;
-static const char *ap_pid_fname=NULL;
-static apr_lock_t *accept_lock;
-static const char *ap_lock_fname;
-static int ap_daemons_to_start=0;
-static int ap_daemons_min_free=0;
-static int ap_daemons_max_free=0;
-static int ap_daemons_limit=0;
-
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across SIGWINCH restarts. We use this
- * value to optimize routines that have to scan the entire scoreboard.
- */
-int ap_max_daemons_limit = -1;
-server_rec *ap_server_conf;
-
-char ap_coredump_dir[MAX_STRING_LEN];
-
-/* *Non*-shared http_main globals... */
-
-static apr_socket_t *sd;
-static fd_set listenfds;
-static int listenmaxfd;
-
-/* one_process --- debugging mode variable; can be set from the command line
- * with the -X flag. If set, this gets you the child_main loop running
- * in the process which originally started up (no detach, no make_child),
- * which is a pretty nice debugging environment. (You'll get a SIGHUP
- * early in standalone_main; just continue through. This is the server
- * trying to kill off any child processes which it might have lying
- * around --- Apache doesn't keep track of their pids, it just sends
- * SIGHUP to the process group, ignoring it in the root process.
- * Continue through and you'll be fine.).
- */
-
-static int one_process = 0;
-
-static apr_pool_t *pconf; /* Pool for config stuff */
-static apr_pool_t *pchild; /* Pool for httpd child stuff */
-
-static pid_t ap_my_pid; /* it seems silly to call getpid all the time */
-#ifndef MULTITHREAD
-static int my_child_num;
-#endif
-
-#ifdef TPF
-int tpf_child = 0;
-char tpf_server_name[INETD_SERVNAME_LENGTH+1];
-#endif /* TPF */
-
-#ifdef GPROF
-/*
- * change directory for gprof to plop the gmon.out file
- * configure in httpd.conf:
- * GprofDir logs/ -> $ServerRoot/logs/gmon.out
- * GprofDir logs/% -> $ServerRoot/logs/gprof.$pid/gmon.out
- */
-static void chdir_for_gprof(void)
-{
- core_server_config *sconf =
- ap_get_module_config(ap_server_conf->module_config, &core_module);
- char *dir = sconf->gprof_dir;
- const char *use_dir;
-
- if(dir) {
- apr_status_t res;
- char buf[512];
- int len = strlen(sconf->gprof_dir) - 1;
- if(*(dir + len) == '%') {
- dir[len] = '\0';
- apr_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());
- }
- use_dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);
- res = apr_dir_make(use_dir, 0755, pconf);
- if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
- "gprof: error creating directory %s", dir);
- }
- }
- else {
- use_dir = ap_server_root_relative(pconf, "logs");
- }
-
- chdir(dir);
-}
-#else
-#define chdir_for_gprof()
-#endif
-
-/* XXX - I don't know if TPF will ever use this module or not, so leave
- * the ap_check_signals calls in but disable them - manoj */
-#define ap_check_signals()
-
-/* a clean exit from a child with proper cleanup */
-static void clean_child_exit(int code) __attribute__ ((noreturn));
-static void clean_child_exit(int code)
-{
- if (pchild) {
- apr_pool_destroy(pchild);
- }
- ap_scoreboard_image->servers[my_child_num][0].life_status = SB_WORKING;
- chdir_for_gprof();
- exit(code);
-}
-
-static void expand_lock_fname(apr_pool_t *p)
-{
- /* XXXX possibly bogus cast */
- ap_lock_fname = apr_psprintf(p, "%s.%lu",
- ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());
-}
-
-/* Initialize mutex lock.
- * Done by each child at its birth
- */
-static void accept_mutex_child_init(apr_pool_t *p)
-{
- apr_status_t rv;
-
- rv = apr_lock_child_init(&accept_lock, ap_lock_fname, p);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL,
- "couldn't do child init for accept mutex");
- clean_child_exit(APEXIT_CHILDINIT);
- }
-}
-
-/* Initialize mutex lock.
- * Must be safe to call this on a restart.
- */
-static void accept_mutex_init(apr_pool_t *p)
-{
- apr_status_t rv;
-
- expand_lock_fname(p);
- rv = apr_lock_create(&accept_lock, APR_MUTEX, APR_CROSS_PROCESS, ap_lock_fname, p);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't create accept mutex");
- exit(APEXIT_INIT);
- }
-}
-
-static void accept_mutex_on(void)
-{
- apr_status_t rv = apr_lock_acquire(accept_lock);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't grab the accept mutex");
- exit(APEXIT_CHILDFATAL);
- }
-}
-
-static void accept_mutex_off(void)
-{
- apr_status_t rv = apr_lock_release(accept_lock);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't release the accept mutex");
- exit(APEXIT_CHILDFATAL);
- }
-}
-
-/* On some architectures it's safe to do unserialized accept()s in the single
- * Listen case. But it's never safe to do it in the case where there's
- * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
- * when it's safe in the single Listen case.
- */
-#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
-#else
-#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
-#endif
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = ap_daemons_limit;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_NOT_SUPPORTED;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_DYNAMIC;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = 0;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-#if defined(NEED_WAITPID)
-/*
- Systems without a real waitpid sometimes lose a child's exit while waiting
- for another. Search through the scoreboard for missing children.
- */
-int reap_children(apr_wait_t *status)
-{
- int n, pid;
-
- for (n = 0; n < ap_max_daemons_limit; ++n) {
- ap_sync_scoreboard_image();
- if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
- kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
- ap_update_child_status(AP_CHILD_THREAD_FROM_ID(n), SERVER_DEAD, NULL);
- /* just mark it as having a successful exit status */
- memset(status, 0, sizeof(apr_wait_t));
- return(pid);
- }
- }
- return 0;
-}
-#endif
-
-/* handle all varieties of core dumping signals */
-static void sig_coredump(int sig)
-{
- chdir(ap_coredump_dir);
- apr_signal(sig, SIG_DFL);
- kill(getpid(), sig);
- /* At this point we've got sig blocked, because we're still inside
- * the signal handler. When we leave the signal handler it will
- * be unblocked, and we'll take the signal... and coredump or whatever
- * is appropriate for this particular Unix. In addition the parent
- * will see the real signal we received -- whereas if we called
- * abort() here, the parent would only see SIGABRT.
- */
-}
-
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-static void just_die(int sig)
-{
- clean_child_exit(0);
-}
-
-static void please_die_gracefully(int sig)
-{
- /* clean_child_exit(0); */
- ap_scoreboard_image->servers[my_child_num][0].life_status = SB_IDLE_DIE;
- if (sig == SIGHUP) {
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num),
- SERVER_GRACEFUL, (request_rec *) NULL);
- }
- else {
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num),
- SERVER_IDLE_KILL, (request_rec *) NULL);
- }
-}
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-ap_generation_t volatile ap_my_generation=0;
-
-static void sig_term(int sig)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-static void restart(int sig)
-{
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- if ((is_graceful = (sig == SIGWINCH))) {
- apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
- }
-}
-
-static void set_signals(void)
-{
-#ifndef NO_USE_SIGACTION
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
- if (!one_process) {
- sa.sa_handler = sig_coredump;
-#if defined(SA_ONESHOT)
- sa.sa_flags = SA_ONESHOT;
-#elif defined(SA_RESETHAND)
- sa.sa_flags = SA_RESETHAND;
-#endif
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
-#ifdef SIGBUS
- if (sigaction(SIGBUS, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
-#endif
-#ifdef SIGABORT
- if (sigaction(SIGABORT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
-#endif
-#ifdef SIGABRT
- if (sigaction(SIGABRT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
-#endif
-#ifdef SIGILL
- if (sigaction(SIGILL, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
-#endif
- sa.sa_flags = 0;
- }
- sa.sa_handler = sig_term;
- if (sigaction(SIGTERM, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
-#ifdef SIGINT
- if (sigaction(SIGINT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
-#endif
-#ifdef SIGXCPU
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXCPU, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
-#endif
-#ifdef SIGXFSZ
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXFSZ, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
-#endif
-#ifdef SIGPIPE
- sa.sa_handler = SIG_IGN;
- if (sigaction(SIGPIPE, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
-#endif
-
- /* we want to ignore HUPs and WINCH while we're busy processing one */
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sa.sa_handler = restart;
- if (sigaction(SIGHUP, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
- if (sigaction(SIGWINCH, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
-#else
- if (!one_process) {
- apr_signal(SIGSEGV, sig_coredump);
-#ifdef SIGBUS
- apr_signal(SIGBUS, sig_coredump);
-#endif /* SIGBUS */
-#ifdef SIGABORT
- apr_signal(SIGABORT, sig_coredump);
-#endif /* SIGABORT */
-#ifdef SIGABRT
- apr_signal(SIGABRT, sig_coredump);
-#endif /* SIGABRT */
-#ifdef SIGILL
- apr_signal(SIGILL, sig_coredump);
-#endif /* SIGILL */
-#ifdef SIGXCPU
- apr_signal(SIGXCPU, SIG_DFL);
-#endif /* SIGXCPU */
-#ifdef SIGXFSZ
- apr_signal(SIGXFSZ, SIG_DFL);
-#endif /* SIGXFSZ */
- }
-
- apr_signal(SIGTERM, sig_term);
-#ifdef SIGHUP
- apr_signal(SIGHUP, restart);
-#endif /* SIGHUP */
-#ifdef SIGWINCH
- apr_signal(SIGWINCH, restart);
-#endif /* SIGWINCH */
-#ifdef SIGPIPE
- apr_signal(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
-
-#endif
-}
-
-/*****************************************************************
- * Child process main loop.
- * The following vars are static to avoid getting clobbered by longjmp();
- * they are really private to child_main.
- */
-
-static int srv;
-static apr_socket_t *csd;
-static int requests_this_child;
-static fd_set main_fds;
-
-#define I_AM_TO_SHUTDOWN() \
-(ap_scoreboard_image->servers[my_child_num][0].life_status != SB_WORKING)
-
-int ap_graceful_stop_signalled(void)
-{
- /* not ever called anymore... */
- return 0;
-}
-
-
-static void child_main(int child_num_arg)
-{
- ap_listen_rec *lr;
- ap_listen_rec *last_lr;
- ap_listen_rec *first_lr;
- apr_pool_t *ptrans;
- conn_rec *current_conn;
- apr_status_t stat = APR_EINIT;
- int sockdes;
-
- my_child_num = child_num_arg;
- ap_my_pid = getpid();
- csd = NULL;
- requests_this_child = 0;
- last_lr = NULL;
-
- /* Get a sub context for global allocations in this child, so that
- * we can have cleanups occur when the child exits.
- */
- apr_pool_create(&pchild, pconf);
-
- apr_pool_create(&ptrans, pchild);
-
- /* needs to be done before we switch UIDs so we have permissions */
- reopen_scoreboard(pchild);
- SAFE_ACCEPT(accept_mutex_child_init(pchild));
-
- if (unixd_setup_child()) {
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- ap_run_child_init(pchild, ap_server_conf);
-
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num), SERVER_READY, (request_rec *) NULL);
-
- apr_signal(SIGHUP, please_die_gracefully);
-
- ap_sync_scoreboard_image();
- while (!I_AM_TO_SHUTDOWN()) {
-
- /* Prepare to receive a SIGWINCH due to graceful restart so that
- * we can exit cleanly.
- */
- apr_signal(SIGWINCH, please_die_gracefully);
- apr_signal(SIGTERM, just_die);
-
- /*
- * (Re)initialize this child to a pre-connection state.
- */
-
- current_conn = NULL;
-
- apr_pool_clear(ptrans);
-
- if ((ap_max_requests_per_child > 0
- && requests_this_child++ >= ap_max_requests_per_child)) {
- clean_child_exit(0);
- }
-
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num), SERVER_READY, (request_rec *) NULL);
-
- /*
- * Wait for an acceptable connection to arrive.
- */
-
- /* Lock around "accept", if necessary */
- SAFE_ACCEPT(accept_mutex_on());
-
- for (;;) {
- if (ap_listeners->next) {
- /* more than one socket */
- memcpy(&main_fds, &listenfds, sizeof(fd_set));
- srv = select(listenmaxfd + 1, &main_fds, NULL, NULL, NULL);
-
- if (srv < 0 && errno != EINTR) {
- /* Single Unix documents select as returning errnos
- * EBADF, EINTR, and EINVAL... and in none of those
- * cases does it make sense to continue. In fact
- * on Linux 2.0.x we seem to end up with EFAULT
- * occasionally, and we'd loop forever due to it.
- */
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf, "select: (listen)");
- clean_child_exit(1);
- }
-
- if (srv <= 0)
- continue;
-
- /* we remember the last_lr we searched last time around so that
- we don't end up starving any particular listening socket */
- if (last_lr == NULL) {
- lr = ap_listeners;
- }
- else {
- lr = last_lr->next;
- if (!lr)
- lr = ap_listeners;
- }
- first_lr=lr;
- do {
- apr_os_sock_get(&sockdes, lr->sd);
- if (FD_ISSET(sockdes, &main_fds))
- goto got_listener;
- lr = lr->next;
- if (!lr)
- lr = ap_listeners;
- }
- while (lr != first_lr);
- /* FIXME: if we get here, something bad has happened, and we're
- probably gonna spin forever.
- */
- continue;
- got_listener:
- last_lr = lr;
- sd = lr->sd;
- }
- else {
- /* only one socket, just pretend we did the other stuff */
- sd = ap_listeners->sd;
- }
-
- /* if we accept() something we don't want to die, so we have to
- * defer the exit
- */
- apr_signal(SIGTERM, please_die_gracefully);
- for (;;) {
- ap_sync_scoreboard_image();
- if (I_AM_TO_SHUTDOWN()) {
- /* we didn't get a socket, and we were told to die */
- clean_child_exit(0);
- }
- stat = apr_accept(&csd, sd, ptrans);
- if (stat == APR_SUCCESS || !APR_STATUS_IS_EINTR(stat))
- break;
- }
-
- if (stat == APR_SUCCESS)
- break; /* We have a socket ready for reading */
- else {
-
-/* TODO: this accept result handling stuff should be abstracted...
- * it's already out of date between the various unix mpms
- */
- /* Our old behaviour here was to continue after accept()
- * errors. But this leads us into lots of troubles
- * because most of the errors are quite fatal. For
- * example, EMFILE can be caused by slow descriptor
- * leaks (say in a 3rd party module, or libc). It's
- * foolish for us to continue after an EMFILE. We also
- * seem to tickle kernel bugs on some platforms which
- * lead to never-ending loops here. So it seems best
- * to just exit in most cases.
- */
- switch (stat) {
-#ifdef EPROTO
- /* EPROTO on certain older kernels really means
- * ECONNABORTED, so we need to ignore it for them.
- * See discussion in new-httpd archives nh.9701
- * search for EPROTO.
- *
- * Also see nh.9603, search for EPROTO:
- * There is potentially a bug in Solaris 2.x x<6,
- * and other boxes that implement tcp sockets in
- * userland (i.e. on top of STREAMS). On these
- * systems, EPROTO can actually result in a fatal
- * loop. See PR#981 for example. It's hard to
- * handle both uses of EPROTO.
- */
- case EPROTO:
-#endif
-#ifdef ECONNABORTED
- case ECONNABORTED:
-#endif
- /* Linux generates the rest of these, other tcp
- * stacks (i.e. bsd) tend to hide them behind
- * getsockopt() interfaces. They occur when
- * the net goes sour or the client disconnects
- * after the three-way handshake has been done
- * in the kernel but before userland has picked
- * up the socket.
- */
-#ifdef ECONNRESET
- case ECONNRESET:
-#endif
-#ifdef ETIMEDOUT
- case ETIMEDOUT:
-#endif
-#ifdef EHOSTUNREACH
- case EHOSTUNREACH:
-#endif
-#ifdef ENETUNREACH
- case ENETUNREACH:
-#endif
- break;
-#ifdef ENETDOWN
- case ENETDOWN:
- /*
- * When the network layer has been shut down, there
- * is not much use in simply exiting: the parent
- * would simply re-create us (and we'd fail again).
- * Use the CHILDFATAL code to tear the server down.
- * @@@ Martin's idea for possible improvement:
- * A different approach would be to define
- * a new APEXIT_NETDOWN exit code, the reception
- * of which would make the parent shutdown all
- * children, then idle-loop until it detected that
- * the network is up again, and restart the children.
- * Ben Hyde noted that temporary ENETDOWN situations
- * occur in mobile IP.
- */
- ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf,
- "apr_accept: giving up.");
- clean_child_exit(APEXIT_CHILDFATAL);
-#endif /*ENETDOWN*/
-
-#ifdef TPF
- case EINACT:
- ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf,
- "offload device inactive");
- clean_child_exit(APEXIT_CHILDFATAL);
- break;
- default:
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
- "select/accept error (%u)", stat);
- clean_child_exit(APEXIT_CHILDFATAL);
-#else
- default:
- ap_log_error(APLOG_MARK, APLOG_ERR, stat, ap_server_conf,
- "apr_accept: (client socket)");
- clean_child_exit(1);
-#endif
- }
- }
-
- ap_sync_scoreboard_image();
- if (I_AM_TO_SHUTDOWN()) {
- clean_child_exit(0);
- }
- }
-
- SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
-
- /* We've got a socket, let's at least process one request off the
- * socket before we accept a graceful restart request. We set
- * the signal to ignore because we don't want to disturb any
- * third party code.
- */
- apr_signal(SIGWINCH, SIG_IGN);
- /*
- * We now have a connection, so set it up with the appropriate
- * socket options, file descriptors, and read/write buffers.
- */
-
- apr_os_sock_get(&sockdes, csd);
-
- if (sockdes >= FD_SETSIZE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
- "new file descriptor %d is too large; you probably need "
- "to rebuild Apache with a larger FD_SETSIZE "
- "(currently %d)",
- sockdes, FD_SETSIZE);
- apr_socket_close(csd);
- ap_sync_scoreboard_image();
- continue;
- }
-
-#ifdef TPF
- if (sockdes == 0) { /* 0 is invalid socket for TPF */
- ap_sync_scoreboard_image();
- continue;
- }
-#endif
-
- ap_sock_disable_nagle(csd);
-
- current_conn = ap_new_connection(ptrans, ap_server_conf, csd,
- my_child_num);
- if (current_conn) {
- ap_process_connection(current_conn);
- ap_lingering_close(current_conn);
- }
-
- ap_sync_scoreboard_image();
- }
- clean_child_exit(0);
-}
-
-
-static int make_child(server_rec *s, int slot)
-{
- int pid;
-
- if (slot + 1 > ap_max_daemons_limit) {
- ap_max_daemons_limit = slot + 1;
- }
-
- if (one_process) {
- apr_signal(SIGHUP, please_die_gracefully);
- apr_signal(SIGINT, please_die_gracefully);
-#ifdef SIGQUIT
- apr_signal(SIGQUIT, SIG_DFL);
-#endif
- apr_signal(SIGTERM, just_die);
- ap_scoreboard_image->servers[slot][0].life_status = SB_WORKING;
- child_main(slot);
- }
-
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(slot), SERVER_STARTING, (request_rec *) NULL);
-
-
-#ifdef _OSD_POSIX
- /* BS2000 requires a "special" version of fork() before a setuid() call */
- if ((pid = os_fork(unixd_config.user_name)) == -1) {
-#elif defined(TPF)
- if ((pid = os_fork(s, slot)) == -1) {
-#else
- if ((pid = fork()) == -1) {
-#endif
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
-
- /* fork didn't succeed. Fix the scoreboard or else
- * it will say SERVER_STARTING forever and ever
- */
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(slot), SERVER_DEAD, (request_rec *) NULL);
-
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again. */
- sleep(10);
-
- return -1;
- }
-
- if (!pid) {
-#ifdef AIX_BIND_PROCESSOR
-/* by default AIX binds to a single processor
- * this bit unbinds children which will then bind to another cpu
- */
-#include <sys/processor.h>
- int status = bindprocessor(BINDPROCESS, (int)getpid(),
- PROCESSOR_CLASS_ANY);
- if (status != OK) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, ap_server_conf,
- "processor unbind failed %d", status);
- }
-#endif
- RAISE_SIGSTOP(MAKE_CHILD);
- /* Disable the restart signal handlers and enable the please_die_gracefully stuff.
- * Note that since restart() just notes that a restart has been
- * requested there's no race condition here.
- */
- apr_signal(SIGHUP, please_die_gracefully);
- apr_signal(SIGWINCH, please_die_gracefully);
- apr_signal(SIGTERM, just_die);
- ap_scoreboard_image->servers[slot][0].life_status = SB_WORKING;
- child_main(slot);
- }
-
- ap_scoreboard_image->parent[slot].pid = pid;
-#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[slot]), 0);
- force_write(scoreboard_fd, &ap_scoreboard_image->parent[slot],
- sizeof(parent_score));
-#endif
-
- return 0;
-}
-
-
-/* start up a bunch of children */
-static void startup_children(int number_to_start)
-{
- int i;
-
- for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
- if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
- continue;
- }
- if (make_child(ap_server_conf, i) < 0) {
- break;
- }
- --number_to_start;
- }
-}
-
-
-/*
- * idle_spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int idle_spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
-static void perform_idle_server_maintenance(void)
-{
- int i;
- int to_kill;
- int idle_count;
- short_score *ss;
- int free_length;
- int free_slots[MAX_SPAWN_RATE];
- int last_non_dead;
- int total_non_dead;
-
- /* initialize the free_list */
- free_length = 0;
-
- to_kill = -1;
- idle_count = 0;
- last_non_dead = -1;
- total_non_dead = 0;
-
- ap_sync_scoreboard_image();
- for (i = 0; i < ap_daemons_limit; ++i) {
- int status;
-
- if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
- break;
- ss = &ap_scoreboard_image->servers[i][0];
- status = ss->status;
- if (status == SERVER_DEAD) {
- /* try to keep children numbers as low as possible */
- if (free_length < idle_spawn_rate) {
- free_slots[free_length] = i;
- ++free_length;
- }
- }
- else {
- /* We consider a starting server as idle because we started it
- * at least a cycle ago, and if it still hasn't finished starting
- * then we're just going to swamp things worse by forking more.
- * So we hopefully won't need to fork more if we count it.
- * This depends on the ordering of SERVER_READY and SERVER_STARTING.
- */
- if (status <= SERVER_READY) {
- ++ idle_count;
- /* always kill the highest numbered child if we have to...
- * no really well thought out reason ... other than observing
- * the server behaviour under linux where lower numbered children
- * tend to service more hits (and hence are more likely to have
- * their data in cpu caches).
- */
- to_kill = i;
- }
-
- ++total_non_dead;
- last_non_dead = i;
- }
- }
- ap_max_daemons_limit = last_non_dead + 1;
- if (idle_count > ap_daemons_max_free) {
- /* kill off one child... we use SIGWINCH because that'll cause it to
- * shut down gracefully, in case it happened to pick up a request
- * while we were counting
- */
- kill(ap_scoreboard_image->parent[to_kill].pid, SIGWINCH);
- idle_spawn_rate = 1;
- }
- else if (idle_count < ap_daemons_min_free) {
- /* terminate the free list */
- if (free_length == 0) {
- /* only report this condition once */
- static int reported = 0;
-
- if (!reported) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
- "server reached MaxClients setting, consider"
- " raising the MaxClients setting");
- reported = 1;
- }
- idle_spawn_rate = 1;
- }
- else {
- if (idle_spawn_rate >= 8) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "server seems busy, (you may need "
- "to increase StartServers, or Min/MaxSpareServers), "
- "spawning %d children, there are %d idle, and "
- "%d total children", idle_spawn_rate,
- idle_count, total_non_dead);
- }
- for (i = 0; i < free_length; ++i) {
-#ifdef TPF
- if (make_child(ap_server_conf, free_slots[i]) == -1) {
- if(free_length == 1) {
- shutdown_pending = 1;
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, ap_server_conf,
- "No active child processes: shutting down");
- }
- }
-#else
- make_child(ap_server_conf, free_slots[i]);
-#endif /* TPF */
- }
- /* the next time around we want to spawn twice as many if this
- * wasn't good enough, but not if we've just done a graceful
- */
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
- }
- else if (idle_spawn_rate < MAX_SPAWN_RATE) {
- idle_spawn_rate *= 2;
- }
- }
- }
- else {
- idle_spawn_rate = 1;
- }
-}
-
-static int setup_listeners(server_rec *s)
-{
- ap_listen_rec *lr;
- int sockdes;
-
- if (ap_setup_listeners(s) < 1 ) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
- "no listening sockets available, shutting down");
- return -1;
- }
-
- listenmaxfd = -1;
- FD_ZERO(&listenfds);
- for (lr = ap_listeners; lr; lr = lr->next) {
- apr_os_sock_get(&sockdes, lr->sd);
- FD_SET(sockdes, &listenfds);
- if (sockdes > listenmaxfd) {
- listenmaxfd = sockdes;
- }
- }
- return 0;
-}
-
-/*****************************************************************
- * Executive routines.
- */
-
-int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
-{
- int index;
- int remaining_children_to_start;
-
- pconf = _pconf;
-
- ap_server_conf = s;
-
- ap_log_pid(pconf, ap_pid_fname);
-
- if (setup_listeners(s)) {
- /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
- return 1;
- }
-
- SAFE_ACCEPT(accept_mutex_init(pconf));
- if (!is_graceful) {
- ap_create_scoreboard(pconf, SB_SHARED);
- }
-#ifdef SCOREBOARD_FILE
- else {
- ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
- ap_note_cleanups_for_fd(pconf, scoreboard_fd);
- }
-#endif
-
- set_signals();
-
- if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
- ap_daemons_max_free = ap_daemons_min_free + 1;
-
- /* If we're doing a graceful_restart then we're going to see a lot
- * of children exiting immediately when we get into the main loop
- * below (because we just sent them SIGWINCH). This happens pretty
- * rapidly... and for each one that exits we'll start a new one until
- * we reach at least daemons_min_free. But we may be permitted to
- * start more than that, so we'll just keep track of how many we're
- * supposed to start up without the 1 second penalty between each fork.
- */
- remaining_children_to_start = ap_daemons_to_start;
- if (remaining_children_to_start > ap_daemons_limit) {
- remaining_children_to_start = ap_daemons_limit;
- }
- if (!is_graceful) {
- startup_children(remaining_children_to_start);
- remaining_children_to_start = 0;
- }
- else {
- /* give the system some time to recover before kicking into
- * exponential mode */
- hold_off_on_exponential_spawning = 10;
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "%s configured -- resuming normal operations",
- ap_get_server_version());
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "Server built: %s", ap_get_server_built());
- restart_pending = shutdown_pending = 0;
-
- while (!restart_pending && !shutdown_pending) {
- int child_slot;
- apr_wait_t status;
- /* this is a memory leak, but I'll fix it later. */
- apr_proc_t pid;
-
- ap_wait_or_timeout(&status, &pid, pconf);
-
- /* XXX: if it takes longer than 1 second for all our children
- * to start up and get into IDLE state then we may spawn an
- * extra child
- */
- if (pid.pid != -1) {
- ap_process_child_status(&pid, status);
- /* non-fatal death... note that it's gone in the scoreboard. */
- ap_sync_scoreboard_image();
- child_slot = find_child_by_pid(&pid);
- if (child_slot >= 0) {
- (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(child_slot), SERVER_DEAD,
- (request_rec *) NULL);
- if (remaining_children_to_start
- && child_slot < ap_daemons_limit) {
- /* we're still doing a 1-for-1 replacement of dead
- * children with new children
- */
- make_child(ap_server_conf, child_slot);
- --remaining_children_to_start;
- }
-#if APR_HAS_OTHER_CHILD
- }
- else if (apr_proc_other_child_read(&pid, status) == 0) {
- /* handled */
-#endif
- }
- else if (is_graceful) {
- /* Great, we've probably just lost a slot in the
- * scoreboard. Somehow we don't know about this
- * child.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
- 0, ap_server_conf,
- "long lost child came home! (pid %ld)", (long)pid.pid);
- }
- /* Don't perform idle maintenance when a child dies,
- * only do it when there's a timeout. Remember only a
- * finite number of children can die, and it's pretty
- * pathological for a lot to die suddenly.
- */
- continue;
- }
- else if (remaining_children_to_start) {
- /* we hit a 1 second timeout in which none of the previous
- * generation of children needed to be reaped... so assume
- * they're all done, and pick up the slack if any is left.
- */
- startup_children(remaining_children_to_start);
- remaining_children_to_start = 0;
- /* In any event we really shouldn't do the code below because
- * few of the servers we just started are in the IDLE state
- * yet, so we'd mistakenly create an extra server.
- */
- continue;
- }
-
- perform_idle_server_maintenance();
-#ifdef TPF
- shutdown_pending = os_check_server(tpf_server_name);
- ap_check_signals();
- sleep(1);
-#endif /*TPF */
- }
-
- if (shutdown_pending) {
- /* Time to gracefully shut down:
- * Kill child processes, tell them to call child_exit, etc...
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
-
- /* cleanup pid file on normal shutdown */
- {
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
- 0, ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "caught SIGTERM, shutting down");
- return 1;
- }
-
- /* we've been told to restart */
- apr_signal(SIGHUP, SIG_IGN);
- apr_signal(SIGWINCH, SIG_IGN);
- if (one_process) {
- /* not worth thinking about */
- return 1;
- }
-
- /* advance to the next generation */
- /* XXX: we really need to make sure this new generation number isn't in
- * use by any of the children.
- */
- ++ap_my_generation;
- ap_scoreboard_image->global.running_generation = ap_my_generation;
- update_scoreboard_global();
-
- for (index = 0; index < ap_daemons_limit; ++index) {
- ap_scoreboard_image->servers[index][0].life_status = SB_IDLE_DIE;
- }
-
- if (is_graceful) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGWINCH received. Doing graceful restart");
-
- /* kill off the idle ones */
- if (unixd_killpg(getpgrp(), SIGWINCH) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGWINCH");
- }
-#ifndef SCOREBOARD_FILE
- /* This is mostly for debugging... so that we know what is still
- * gracefully dealing with existing request. But we can't really
- * do it if we're in a SCOREBOARD_FILE because it'll cause
- * corruption too easily.
- */
- ap_sync_scoreboard_image();
- for (index = 0; index < ap_daemons_limit; ++index) {
- if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
- ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL;
- }
- }
-#endif
- }
- else {
- /* Kill 'em off */
- if (unixd_killpg(getpgrp(), SIGHUP) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP");
- }
- ap_reclaim_child_processes(0); /* Not when just starting up */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGHUP received. Attempting to restart");
- }
-
- return 0;
-}
-
-static void prefork_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- static int restart_num = 0;
- int no_detach = 0;
-
- no_detach = !!ap_exists_config_define("NO_DETACH");
- one_process = !!ap_exists_config_define("ONE_PROCESS");
-
- /* sigh, want this only the second time around */
- if (restart_num++ == 1) {
- is_graceful = 0;
-
- if (!one_process && !no_detach) {
- apr_proc_detach();
- }
-
- ap_my_pid = getpid();
- }
-
- unixd_pre_config(ptemp);
- ap_listen_pre_config();
- ap_daemons_to_start = DEFAULT_START_DAEMON;
- ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
- ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
- ap_daemons_limit = HARD_SERVER_LIMIT;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_scoreboard_fname = DEFAULT_SCOREBOARD;
- ap_lock_fname = DEFAULT_LOCKFILE;
- ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
- ap_extended_status = 0;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-}
-
-static void prefork_hooks(apr_pool_t *p)
-{
-#ifdef AUX3
- (void) set42sig();
-#endif
-
- ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in <VirtualHost>";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_scoreboard_fname = arg;
- return NULL;
-}
-
-static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_lock_fname = arg;
- return NULL;
-}
-
-static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_to_start = atoi(arg);
- return NULL;
-}
-
-static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_min_free = atoi(arg);
- if (ap_daemons_min_free <= 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareServers set to non-positive.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Resetting to 1 to avoid almost certain Apache failure.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Please read the documentation.");
- ap_daemons_min_free = 1;
- }
-
- return NULL;
-}
-
-static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_max_free = atoi(arg);
- return NULL;
-}
-
-static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_limit = atoi(arg);
- if (ap_daemons_limit > HARD_SERVER_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: MaxClients of %d exceeds compile time limit "
- "of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering MaxClients to %d. To increase, please "
- "see the", HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_SERVER_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- ap_daemons_limit = HARD_SERVER_LIMIT;
- }
- else if (ap_daemons_limit < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require MaxClients > 0, setting to 1");
- ap_daemons_limit = 1;
- }
- return NULL;
-}
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_max_requests_per_child = atoi(arg);
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-static const command_rec prefork_cmds[] = {
-UNIX_DAEMON_COMMANDS
-LISTEN_COMMANDS
-AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
- "A file for logging the server process ID"),
-AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
- "A file for Apache to maintain runtime process management information"),
-AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
- "The lockfile used when Apache needs to lock the accept() call"),
-AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
- "Number of child processes launched at server startup"),
-AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
- "Minimum number of idle children, to handle request spikes"),
-AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF,
- "Maximum number of idle children"),
-AP_INIT_TAKE1("MaxClients", set_server_limit, NULL, RSRC_CONF,
- "Maximum number of children alive at the same time"),
-AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
- "Maximum number of requests a particular child serves before dying."),
-AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
- "The location of the directory Apache changes to before dumping core"),
-{ NULL }
-};
-
-module AP_MODULE_DECLARE_DATA mpm_prefork_module = {
- MPM20_MODULE_STUFF,
- NULL, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- prefork_cmds, /* command apr_table_t */
- prefork_hooks, /* register hooks */
-};
diff --git a/server/mpm/spmt_os2/.cvsignore b/server/mpm/spmt_os2/.cvsignore
deleted file mode 100644
index dc53ac865d..0000000000
--- a/server/mpm/spmt_os2/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*.lo
-*.la
-Makefile
-.deps
-.libs
diff --git a/server/mpm/spmt_os2/Makefile.in b/server/mpm/spmt_os2/Makefile.in
deleted file mode 100644
index 105f39128f..0000000000
--- a/server/mpm/spmt_os2/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-LTLIBRARY_NAME = libspmt_os2.la
-LTLIBRARY_SOURCES = spmt_os2.c
-
-include $(top_srcdir)/build/ltlib.mk
diff --git a/server/mpm/spmt_os2/config5.m4 b/server/mpm/spmt_os2/config5.m4
deleted file mode 100644
index 770b9d2212..0000000000
--- a/server/mpm/spmt_os2/config5.m4
+++ /dev/null
@@ -1,5 +0,0 @@
-if test "$MPM_NAME" = "spmt_os2" ; then
- AC_CACHE_SAVE
- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
- APR_ADDTO(CFLAGS,-Zmt)
-fi
diff --git a/server/mpm/spmt_os2/mpm.h b/server/mpm/spmt_os2/mpm.h
deleted file mode 100644
index 96062ed7d6..0000000000
--- a/server/mpm/spmt_os2/mpm.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_SPMT_OS2_H
-#define APACHE_MPM_SPMT_OS2_H
-
-#define SPMT_OS2_MPM
-
-#include "httpd.h"
-#include "mpm_default.h"
-#include "scoreboard.h"
-
-#define MPM_NAME "SPMT_OS2"
-
-extern char ap_coredump_dir[MAX_STRING_LEN];
-extern server_rec *ap_server_conf;
-extern int ap_threads_per_child;
-
-#endif /* APACHE_MPM_SPMT_OS2_H */
diff --git a/server/mpm/spmt_os2/mpm_default.h b/server/mpm/spmt_os2/mpm_default.h
deleted file mode 100644
index c554fddf60..0000000000
--- a/server/mpm/spmt_os2/mpm_default.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-/* Number of servers to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_DAEMON
-#define DEFAULT_START_DAEMON 5
-#endif
-
-/* Maximum number of *free* server processes --- more than this, and
- * they will die off.
- */
-
-#ifndef DEFAULT_MAX_FREE_DAEMON
-#define DEFAULT_MAX_FREE_DAEMON 10
-#endif
-
-/* Minimum --- fewer than this, and more will be created */
-
-#ifndef DEFAULT_MIN_FREE_DAEMON
-#define DEFAULT_MIN_FREE_DAEMON 5
-#endif
-
-/* SPMT_OS2 only ever has 1 process */
-#define HARD_SERVER_LIMIT 1
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 256
-#endif
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-/* AP_CHILD_THREAD_FROM_ID is used by the scoreboard. */
-#define AP_CHILD_THREAD_FROM_ID(i) 0, i
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/spmt_os2/spmt_os2.c b/server/mpm/spmt_os2/spmt_os2.c
deleted file mode 100644
index b991c9df36..0000000000
--- a/server/mpm/spmt_os2/spmt_os2.c
+++ /dev/null
@@ -1,1322 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#define CORE_PRIVATE
-#define INCL_DOS
-#define INCL_DOSERRORS
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "mpm_default.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h"
-#include "http_core.h" /* for get_remote_host */
-#include "http_connection.h"
-#include "mpm.h"
-#include "ap_mpm.h"
-#include "ap_listen.h"
-#include "apr_portable.h"
-#include "mpm_common.h"
-#include "apr_strings.h"
-
-#include <os2.h>
-#include <stdlib.h>
-#include <sys/signal.h>
-#include <process.h>
-#include <time.h>
-#include <io.h>
-
-/* config globals */
-
-static int ap_max_requests_per_child=0;
-static char *ap_pid_fname=NULL;
-static int ap_daemons_to_start=0;
-static int ap_daemons_min_free=0;
-static int ap_daemons_max_free=0;
-static int ap_daemons_limit=0;
-
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across SIGUSR1 restarts. We use this
- * value to optimize routines that have to scan the entire scoreboard.
- */
-static int max_daemons_limit = -1;
-int ap_threads_per_child = HARD_THREAD_LIMIT;
-ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */
-
-char ap_coredump_dir[MAX_STRING_LEN];
-
-/* *Non*-shared http_main globals... */
-
-server_rec *ap_server_conf;
-
-/* one_process --- debugging mode variable; can be set from the command line
- * with the -X flag. If set, this gets you the child_main loop running
- * in the process which originally started up (no detach, no make_child),
- * which is a pretty nice debugging environment. (You'll get a SIGHUP
- * early in standalone_main; just continue through. This is the server
- * trying to kill off any child processes which it might have lying
- * around --- Apache doesn't keep track of their pids, it just sends
- * SIGHUP to the process group, ignoring it in the root process.
- * Continue through and you'll be fine.).
- */
-
-static int one_process = 0;
-
-static apr_pool_t *pconf; /* Pool for config stuff */
-
-struct thread_globals {
- int thread_num;
- apr_pool_t *pchild; /* Pool for httpd child stuff */
- int usr1_just_die;
-};
-
-static struct thread_globals **ppthread_globals = NULL;
-
-#define THREAD_GLOBAL(gvar) ((*ppthread_globals)->gvar)
-
-struct thread_control_t {
- apr_wait_t thread_retval;
- char deferred_die;
- ap_generation_t generation; /* generation of this thread */
-} thread_control[HARD_THREAD_LIMIT];
-
-/* a clean exit from a child with proper cleanup */
-static void clean_child_exit(int code)
-{
- if (THREAD_GLOBAL(pchild)) {
- apr_pool_destroy(THREAD_GLOBAL(pchild));
- }
-
- thread_control[THREAD_GLOBAL(thread_num)].deferred_die = 0;
- thread_control[THREAD_GLOBAL(thread_num)].thread_retval = code;
- _endthread();
-}
-
-
-
-static apr_lock_t *accept_mutex = NULL;
-
-static apr_status_t accept_mutex_child_cleanup(void *foo)
-{
- return apr_lock_release(accept_mutex);
-}
-
-/*
- * Initialize mutex lock.
- * Done by each child at it's birth
- */
-static void accept_mutex_child_init(apr_pool_t *p)
-{
- apr_pool_cleanup_register(p, NULL, accept_mutex_child_cleanup, apr_pool_cleanup_null);
-}
-
-/*
- * Initialize mutex lock.
- * Must be safe to call this on a restart.
- */
-static void accept_mutex_init(apr_pool_t *p)
-{
- apr_status_t rc = apr_lock_create(&accept_mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, p);
-
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf,
- "Error creating accept lock. Exiting!");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-}
-
-static void accept_mutex_on(void)
-{
- apr_status_t rc = apr_lock_acquire(accept_mutex);
-
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf,
- "Error getting accept lock. Exiting!");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-}
-
-static void accept_mutex_off(void)
-{
- apr_status_t rc = apr_lock_release(accept_mutex);
-
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf,
- "Error freeing accept lock. Exiting!");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-}
-
-
-
-/* On some architectures it's safe to do unserialized accept()s in the single
- * Listen case. But it's never safe to do it in the case where there's
- * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
- * when it's safe in the single Listen case.
- */
-#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
-#else
-#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
-#endif
-
-static int find_thread_by_tid(int tid)
-{
- int i;
-
- for (i = 0; i < max_daemons_limit; ++i)
- if (ap_scoreboard_image->servers[0][i].tid == tid)
- return i;
-
- return -1;
-}
-
-/* Finally, this routine is used by the caretaker thread to wait for
- * a while...
- */
-
-/* number of calls to wait_or_timeout between writable probes */
-#ifndef INTERVAL_OF_WRITABLE_PROBES
-#define INTERVAL_OF_WRITABLE_PROBES 10
-#endif
-static int wait_or_timeout_counter;
-
-static int wait_or_timeout(apr_wait_t *status)
-{
- int ret;
- ULONG tid;
-
- ++wait_or_timeout_counter;
- if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
- wait_or_timeout_counter = 0;
-#if APR_HAS_OTHER_CHILD
- apr_proc_probe_writable_fds();
-#endif
- }
-
- tid = 0;
- ret = DosWaitThread(&tid, DCWW_NOWAIT);
-
- if (ret == 0) {
- int thread_num = find_thread_by_tid(tid);
- ap_assert( thread_num > 0 );
- *status = thread_control[thread_num].thread_retval;
- return tid;
- }
-
- DosSleep(SCOREBOARD_MAINTENANCE_INTERVAL / 1000);
- return -1;
-}
-
-
-
-/* handle all varieties of core dumping signals */
-static void sig_coredump(int sig)
-{
- chdir(ap_coredump_dir);
- signal(sig, SIG_DFL);
- kill(getpid(), sig);
- /* At this point we've got sig blocked, because we're still inside
- * the signal handler. When we leave the signal handler it will
- * be unblocked, and we'll take the signal... and coredump or whatever
- * is appropriate for this particular Unix. In addition the parent
- * will see the real signal we received -- whereas if we called
- * abort() here, the parent would only see SIGABRT.
- */
-}
-
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-static void just_die(int sig)
-{
- clean_child_exit(0);
-}
-
-
-static void usr1_handler(int sig)
-{
- if (THREAD_GLOBAL(usr1_just_die)) {
- just_die(sig);
- }
- thread_control[THREAD_GLOBAL(thread_num)].deferred_die = 1;
-}
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-
-static void sig_term(int sig)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-static void restart(int sig)
-{
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- is_graceful = sig == SIGUSR1;
-}
-
-static void set_signals(void)
-{
-#ifndef NO_USE_SIGACTION
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
- if (!one_process) {
- sa.sa_handler = sig_coredump;
-#if defined(SA_ONESHOT)
- sa.sa_flags = SA_ONESHOT;
-#elif defined(SA_RESETHAND)
- sa.sa_flags = SA_RESETHAND;
-#endif
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
-#ifdef SIGBUS
- if (sigaction(SIGBUS, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
-#endif
-#ifdef SIGABORT
- if (sigaction(SIGABORT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
-#endif
-#ifdef SIGABRT
- if (sigaction(SIGABRT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
-#endif
-#ifdef SIGILL
- if (sigaction(SIGILL, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
-#endif
- sa.sa_flags = 0;
- }
- sa.sa_handler = sig_term;
- if (sigaction(SIGTERM, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
-#ifdef SIGINT
- if (sigaction(SIGINT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
-#endif
-#ifdef SIGXCPU
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXCPU, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
-#endif
-#ifdef SIGXFSZ
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXFSZ, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
-#endif
-#ifdef SIGPIPE
- sa.sa_handler = SIG_IGN;
- if (sigaction(SIGPIPE, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
-#endif
-
- /* we want to ignore HUPs and USR1 while we're busy processing one */
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGUSR1);
- sa.sa_handler = restart;
- if (sigaction(SIGHUP, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
- if (sigaction(SIGUSR1, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGUSR1)");
-#else
- if (!one_process) {
- signal(SIGSEGV, sig_coredump);
-#ifdef SIGBUS
- signal(SIGBUS, sig_coredump);
-#endif /* SIGBUS */
-#ifdef SIGABORT
- signal(SIGABORT, sig_coredump);
-#endif /* SIGABORT */
-#ifdef SIGABRT
- signal(SIGABRT, sig_coredump);
-#endif /* SIGABRT */
-#ifdef SIGILL
- signal(SIGILL, sig_coredump);
-#endif /* SIGILL */
-#ifdef SIGXCPU
- signal(SIGXCPU, SIG_DFL);
-#endif /* SIGXCPU */
-#ifdef SIGXFSZ
- signal(SIGXFSZ, SIG_DFL);
-#endif /* SIGXFSZ */
- }
-
- signal(SIGTERM, sig_term);
-#ifdef SIGHUP
- signal(SIGHUP, restart);
-#endif /* SIGHUP */
-#ifdef SIGUSR1
- signal(SIGUSR1, restart);
-#endif /* SIGUSR1 */
-#ifdef SIGPIPE
- signal(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
-
-#endif
-}
-
-/*****************************************************************
- * Child process main loop.
- */
-
-AP_DECLARE(void) ap_child_terminate(request_rec *r)
-{
- r->connection->keepalive = 0;
- thread_control[THREAD_GLOBAL(thread_num)].deferred_die = 1;
-}
-
-
-
-int ap_graceful_stop_signalled(void)
-{
- if (thread_control[THREAD_GLOBAL(thread_num)].deferred_die ||
- ap_scoreboard_image->global.running_generation != thread_control[THREAD_GLOBAL(thread_num)].generation) {
- return 1;
- }
- return 0;
-}
-
-
-
-int ap_stop_signalled(void)
-{
- if (shutdown_pending || restart_pending ||
- thread_control[THREAD_GLOBAL(thread_num)].deferred_die ||
- ap_scoreboard_image->global.running_generation != thread_control[THREAD_GLOBAL(thread_num)].generation) {
- return 1;
- }
- return 0;
-}
-
-
-
-static int setup_listen_poll(apr_pool_t *pchild, apr_pollfd_t **listen_poll)
-{
- ap_listen_rec *lr;
- int numfds = 0;
-
- for (lr = ap_listeners; lr; lr = lr->next) {
- numfds++;
- }
-
- apr_poll_setup(listen_poll, numfds, pchild);
-
- for (lr = ap_listeners; lr; lr = lr->next) {
- apr_poll_socket_add(*listen_poll, lr->sd, APR_POLLIN);
- }
- return 0;
-}
-
-
-
-static void thread_main(void *thread_num_arg)
-{
- ap_listen_rec *lr = NULL;
- ap_listen_rec *first_lr = NULL;
- apr_pool_t *ptrans;
- conn_rec *current_conn;
- apr_pool_t *pchild;
- int requests_this_child = 0;
- apr_pollfd_t *listen_poll;
- apr_socket_t *csd = NULL;
- int nsds, rv;
-
- /* Disable the restart signal handlers and enable the just_die stuff.
- * Note that since restart() just notes that a restart has been
- * requested there's no race condition here.
- */
-
- set_signals(); /* signals aren't inherrited by child threads */
- signal(SIGHUP, just_die);
- signal(SIGUSR1, just_die);
- signal(SIGTERM, just_die);
-
- /* Get a sub pool for global allocations in this child, so that
- * we can have cleanups occur when the child exits.
- */
- apr_pool_create(&pchild, pconf);
- *ppthread_globals = (struct thread_globals *)apr_palloc(pchild, sizeof(struct thread_globals));
- THREAD_GLOBAL(thread_num) = (int)thread_num_arg;
- THREAD_GLOBAL(pchild) = pchild;
- thread_control[THREAD_GLOBAL(thread_num)].generation = ap_scoreboard_image->global.running_generation;
- apr_pool_create(&ptrans, pchild);
-
- if (setup_listen_poll(pchild, &listen_poll)) {
- clean_child_exit(1);
- }
-
- /* needs to be done before we switch UIDs so we have permissions */
- SAFE_ACCEPT(accept_mutex_child_init(pchild));
-
- ap_run_child_init(pchild, ap_server_conf);
-
- (void) ap_update_child_status(0, THREAD_GLOBAL(thread_num), SERVER_READY, (request_rec *) NULL);
-
-
- signal(SIGHUP, just_die);
- signal(SIGTERM, just_die);
-
- while (!ap_stop_signalled()) {
- int srv;
- apr_socket_t *sd;
-
- /* Prepare to receive a SIGUSR1 due to graceful restart so that
- * we can exit cleanly.
- */
- THREAD_GLOBAL(usr1_just_die) = 1;
- signal(SIGUSR1, usr1_handler);
-
- /*
- * (Re)initialize this child to a pre-connection state.
- */
-
- current_conn = NULL;
-
- apr_pool_clear(ptrans);
-
- if ((ap_max_requests_per_child > 0
- && requests_this_child++ >= ap_max_requests_per_child)) {
- clean_child_exit(0);
- }
-
- (void) ap_update_child_status(0, THREAD_GLOBAL(thread_num), SERVER_READY, (request_rec *) NULL);
-
- /*
- * Wait for an acceptable connection to arrive.
- */
-
- /* Lock around "accept", if necessary */
- SAFE_ACCEPT(accept_mutex_on());
-
- if (ap_stop_signalled()) {
- clean_child_exit(0);
- }
-
- for (;;) {
- if (ap_listeners->next) {
- /* more than one socket */
- srv = apr_poll(listen_poll, &nsds, -1);
-
- if (srv != APR_SUCCESS) {
- /* Single Unix documents select as returning errnos
- * EBADF, EINTR, and EINVAL... and in none of those
- * cases does it make sense to continue. In fact
- * on Linux 2.0.x we seem to end up with EFAULT
- * occasionally, and we'd loop forever due to it.
- */
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf, "select: (listen)");
- clean_child_exit(1);
- }
-
- /* we remember the last_lr we searched last time around so that
- we don't end up starving any particular listening socket */
- if (first_lr == NULL) {
- first_lr = ap_listeners;
- }
-
- lr = first_lr;
-
- do {
- apr_int16_t event;
-
- if (!lr) {
- lr = ap_listeners;
- }
-
- apr_poll_revents_get(&event, lr->sd, listen_poll);
-
- if (event == APR_POLLIN) {
- first_lr = lr->next;
- break;
- }
- lr = lr->next;
- } while (lr != first_lr);
-
- if (lr == first_lr) {
- continue;
- }
- sd = lr->sd;
- }
- else {
- /* only one socket, just pretend we did the other stuff */
- sd = ap_listeners->sd;
- }
-
- /* if we accept() something we don't want to die, so we have to
- * defer the exit
- */
- THREAD_GLOBAL(usr1_just_die) = 0;
- rv = apr_accept(&csd, sd, ptrans);
-
- if (APR_STATUS_IS_SUCCESS(rv)) {
- break; /* We have a socket ready for reading */
- }
- else if (APR_STATUS_IS_ECONNABORTED(rv)
- || APR_STATUS_IS_ECONNRESET(rv)
- || APR_STATUS_IS_ETIMEDOUT(rv)
- || APR_STATUS_IS_EHOSTUNREACH(rv)
- || APR_STATUS_IS_ENETUNREACH(rv)) {
-
- /* Our old behaviour here was to continue after accept()
- * errors. But this leads us into lots of troubles
- * because most of the errors are quite fatal. For
- * example, EMFILE can be caused by slow descriptor
- * leaks (say in a 3rd party module, or libc). It's
- * foolish for us to continue after an EMFILE. We also
- * seem to tickle kernel bugs on some platforms which
- * lead to never-ending loops here. So it seems best
- * to just exit in most cases.
- */
-
- /* Linux generates most of these, other tcp
- * stacks (i.e. bsd) tend to hide them behind
- * getsockopt() interfaces. They occur when
- * the net goes sour or the client disconnects
- * after the three-way handshake has been done
- * in the kernel but before userland has picked
- * up the socket.
- */
- break;
- }
- else if (APR_STATUS_IS_EINTR(rv)) {
- /* We only get hit by an EINTR if the parent is
- * killing us off
- */
- clean_child_exit(0);
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
- "accept: (client socket)");
- clean_child_exit(1);
- }
-
- if (ap_stop_signalled()) {
- clean_child_exit(0);
- }
- THREAD_GLOBAL(usr1_just_die) = 1;
- }
-
- SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
-
- /* We've got a socket, let's at least process one request off the
- * socket before we accept a graceful restart request. We set
- * the signal to ignore because we don't want to disturb any
- * third party code.
- */
- signal(SIGUSR1, SIG_IGN);
-
- /*
- * We now have a connection, so set it up with the appropriate
- * socket options, file descriptors, and read/write buffers.
- */
-
- ap_sock_disable_nagle(csd);
-
- current_conn = ap_new_connection(ptrans, ap_server_conf, csd,
- THREAD_GLOBAL(thread_num));
-
- if (current_conn) {
- ap_process_connection(current_conn);
- ap_lingering_close(current_conn);
- }
- }
-
- clean_child_exit(0);
-}
-
-
-static int make_child(server_rec *s, int slot)
-{
- TID tid;
-
- if (slot + 1 > max_daemons_limit) {
- max_daemons_limit = slot + 1;
- }
-
- if (one_process) {
- struct thread_globals *parent_globals = *ppthread_globals;
- signal(SIGHUP, just_die);
- signal(SIGINT, just_die);
-#ifdef SIGQUIT
- signal(SIGQUIT, SIG_DFL);
-#endif
- signal(SIGTERM, just_die);
- thread_main((void *)slot);
- *ppthread_globals = parent_globals;
- }
-
- ap_update_child_status(0, slot, SERVER_STARTING, (request_rec *) NULL);
-
- if ((tid = _beginthread(thread_main, NULL, 256*1024, (void *)slot)) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s, "_beginthread: Unable to create new thread");
-
- /* _beginthread didn't succeed. Fix the scoreboard or else
- * it will say SERVER_STARTING forever and ever
- */
- (void) ap_update_child_status(0, slot, SERVER_DEAD, (request_rec *) NULL);
-
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to _beginthread over and
- over and over again. */
- sleep(10);
-
- return -1;
- }
-
- ap_scoreboard_image->servers[0][slot].tid = tid;
- return 0;
-}
-
-
-/* start up a bunch of children */
-static void startup_children(int number_to_start)
-{
- int i;
-
- for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
- if (ap_scoreboard_image->servers[0][i].status != SERVER_DEAD) {
- continue;
- }
- if (make_child(ap_server_conf, i) < 0) {
- break;
- }
- --number_to_start;
- }
-}
-
-
-/*
- * idle_spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int idle_spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
-static void perform_idle_server_maintenance(void)
-{
- int i;
- int to_kill;
- int idle_count;
- short_score *ss;
- int free_length;
- int free_slots[MAX_SPAWN_RATE];
- int last_non_dead;
- int total_non_dead;
-
- /* initialize the free_list */
- free_length = 0;
-
- to_kill = -1;
- idle_count = 0;
- last_non_dead = -1;
- total_non_dead = 0;
-
- for (i = 0; i < ap_daemons_limit; ++i) {
- int status;
-
- if (i >= max_daemons_limit && free_length == idle_spawn_rate)
- break;
- ss = &ap_scoreboard_image->servers[0][i];
- status = ss->status;
- if (status == SERVER_DEAD) {
- /* try to keep children numbers as low as possible */
- if (free_length < idle_spawn_rate) {
- free_slots[free_length] = i;
- ++free_length;
- }
- }
- else {
- /* We consider a starting server as idle because we started it
- * at least a cycle ago, and if it still hasn't finished starting
- * then we're just going to swamp things worse by forking more.
- * So we hopefully won't need to fork more if we count it.
- * This depends on the ordering of SERVER_READY and SERVER_STARTING.
- */
- if (status <= SERVER_READY) {
- ++ idle_count;
- /* always kill the highest numbered child if we have to...
- * no really well thought out reason ... other than observing
- * the server behaviour under linux where lower numbered children
- * tend to service more hits (and hence are more likely to have
- * their data in cpu caches).
- */
- to_kill = i;
- }
-
- ++total_non_dead;
- last_non_dead = i;
- }
- }
- max_daemons_limit = last_non_dead + 1;
- if (idle_count > ap_daemons_max_free) {
- /* kill off one child... we use SIGUSR1 because that'll cause it to
- * shut down gracefully, in case it happened to pick up a request
- * while we were counting
- */
- thread_control[to_kill].deferred_die = 1;
- idle_spawn_rate = 1;
- }
- else if (idle_count < ap_daemons_min_free) {
- /* terminate the free list */
- if (free_length == 0) {
- /* only report this condition once */
- static int reported = 0;
-
- if (!reported) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
- "server reached MaxClients setting, consider"
- " raising the MaxClients setting");
- reported = 1;
- }
- idle_spawn_rate = 1;
- }
- else {
- if (idle_spawn_rate >= 8) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "server seems busy, (you may need "
- "to increase StartServers, or Min/MaxSpareServers), "
- "spawning %d children, there are %d idle, and "
- "%d total children", idle_spawn_rate,
- idle_count, total_non_dead);
- }
- for (i = 0; i < free_length; ++i) {
- make_child(ap_server_conf, free_slots[i]);
- }
- /* the next time around we want to spawn twice as many if this
- * wasn't good enough, but not if we've just done a graceful
- */
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
- }
- else if (idle_spawn_rate < MAX_SPAWN_RATE) {
- idle_spawn_rate *= 2;
- }
- }
- }
- else {
- idle_spawn_rate = 1;
- }
-}
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = max_daemons_limit;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_DYNAMIC;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_NOT_SUPPORTED;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = ap_threads_per_child;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-/*****************************************************************
- * Executive routines.
- */
-
-int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
-{
- int remaining_children_to_start;
- int i;
- apr_status_t status;
-
- pconf = _pconf;
- ap_server_conf = s;
- ap_log_pid(pconf, ap_pid_fname);
-
- if ((status = ap_listen_open(s->process, s->port)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, status, s,
- "no listening sockets available, shutting down");
- return -1;
- }
-
- SAFE_ACCEPT(accept_mutex_init(pconf));
-
- if (!is_graceful) {
- ap_create_scoreboard(pconf, SB_NOT_SHARED);
- memset(thread_control, 0, sizeof(thread_control));
- }
-
- set_signals();
- DosSetMaxFH(ap_daemons_limit * 2);
-
- if (ppthread_globals == NULL) {
- if (DosAllocThreadLocalMemory(1, (PULONG *)&ppthread_globals)) {
- ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, ap_server_conf,
- "Error allocating thread local storage"
- "Apache is exiting!");
- } else {
- *ppthread_globals = (struct thread_globals *)apr_palloc(pconf, sizeof(struct thread_globals));
- }
- }
-
- if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
- ap_daemons_max_free = ap_daemons_min_free + 1;
-
- /* If we're doing a graceful_restart then we're going to see a lot
- * of children exiting immediately when we get into the main loop
- * below (because we just sent them SIGUSR1). This happens pretty
- * rapidly... and for each one that exits we'll start a new one until
- * we reach at least daemons_min_free. But we may be permitted to
- * start more than that, so we'll just keep track of how many we're
- * supposed to start up without the 1 second penalty between each fork.
- */
- remaining_children_to_start = ap_daemons_to_start;
- if (remaining_children_to_start > ap_daemons_limit) {
- remaining_children_to_start = ap_daemons_limit;
- }
- if (!is_graceful) {
- startup_children(remaining_children_to_start);
- remaining_children_to_start = 0;
- }
- else {
- /* give the system some time to recover before kicking into
- * exponential mode */
- hold_off_on_exponential_spawning = 10;
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "%s configured -- resuming normal operations",
- ap_get_server_version());
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "Server built: %s", ap_get_server_built());
- restart_pending = shutdown_pending = 0;
-
- printf("%s \n", ap_get_server_version());
-
- while (!restart_pending && !shutdown_pending) {
- int thread_slot;
- apr_wait_t status;
- int tid = wait_or_timeout(&status);
-
- /* XXX: if it takes longer than 1 second for all our children
- * to start up and get into IDLE state then we may spawn an
- * extra child
- */
- if (tid >= 0) {
- apr_proc_t dummyproc;
- dummyproc.pid = tid;
- ap_process_child_status(&dummyproc, status);
- /* non-fatal death... note that it's gone in the scoreboard. */
- thread_slot = find_thread_by_tid(tid);
- if (thread_slot >= 0) {
- (void) ap_update_child_status(0, thread_slot, SERVER_DEAD,
- (request_rec *) NULL);
- if (remaining_children_to_start
- && thread_slot < ap_daemons_limit) {
- /* we're still doing a 1-for-1 replacement of dead
- * children with new children
- */
- make_child(ap_server_conf, thread_slot);
- --remaining_children_to_start;
- }
-#if APR_HAS_OTHER_CHILD
-/* TODO: this won't work, we waited on a thread not a process
- }
- else if (reap_other_child(pid, status) == 0) {
-*/
-#endif
- }
- else if (is_graceful) {
- /* Great, we've probably just lost a slot in the
- * scoreboard. Somehow we don't know about this
- * child.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf,
- "long lost child came home! (tid %d)", tid);
- }
- /* Don't perform idle maintenance when a child dies,
- * only do it when there's a timeout. Remember only a
- * finite number of children can die, and it's pretty
- * pathological for a lot to die suddenly.
- */
- continue;
- }
- else if (remaining_children_to_start) {
- /* we hit a 1 second timeout in which none of the previous
- * generation of children needed to be reaped... so assume
- * they're all done, and pick up the slack if any is left.
- */
- startup_children(remaining_children_to_start);
- remaining_children_to_start = 0;
- /* In any event we really shouldn't do the code below because
- * few of the servers we just started are in the IDLE state
- * yet, so we'd mistakenly create an extra server.
- */
- continue;
- }
-
- perform_idle_server_maintenance();
- }
-
- if (shutdown_pending) {
- /* Time to gracefully shut down */
- const char *pidfile = NULL;
- int slot;
- TID tid;
- ULONG rc;
- ap_listen_rec *lr;
-
- for (lr = ap_listeners; lr; lr = lr->next) {
- apr_socket_close(lr->sd);
- DosSleep(0);
- }
-
- /* Kill off running threads */
- for (slot=0; slot<max_daemons_limit; slot++) {
- if (ap_scoreboard_image->servers[0][slot].status != SERVER_DEAD) {
- tid = ap_scoreboard_image->servers[0][slot].tid;
- rc = DosKillThread(tid);
-
- if (rc != ERROR_INVALID_THREADID) { // Already dead, ignore
- if (rc == 0) {
- rc = DosWaitThread(&tid, DCWW_WAIT);
-
- if (rc) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf,
- "error %lu waiting for thread to terminate", rc);
- }
- } else {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf,
- "error %lu killing thread", rc);
- }
- }
- }
- }
-
- /* cleanup pid file on normal shutdown */
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
- ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "caught SIGTERM, shutting down");
- return 1;
- }
-
- /* we've been told to restart */
- signal(SIGHUP, SIG_IGN);
- signal(SIGUSR1, SIG_IGN);
-
- if (one_process) {
- /* not worth thinking about */
- return 1;
- }
-
- /* advance to the next generation */
- /* XXX: we really need to make sure this new generation number isn't in
- * use by any of the children.
- */
- ++ap_scoreboard_image->global.running_generation;
-
- if (is_graceful) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGUSR1 received. Doing graceful restart");
-
- /* kill off the idle ones */
- for (i = 0; i < ap_daemons_limit; ++i) {
- thread_control[i].deferred_die = 1;
- }
-
- /* This is mostly for debugging... so that we know what is still
- * gracefully dealing with existing request. But we can't really
- * do it if we're in a SCOREBOARD_FILE because it'll cause
- * corruption too easily.
- */
- for (i = 0; i < ap_daemons_limit; ++i) {
- if (ap_scoreboard_image->servers[0][i].status != SERVER_DEAD) {
- ap_scoreboard_image->servers[0][i].status = SERVER_GRACEFUL;
- }
- }
- }
- else {
- /* Kill 'em off */
- for (i = 0; i < ap_daemons_limit; ++i) {
- DosKillThread(ap_scoreboard_image->servers[0][i].tid);
- }
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGHUP received. Attempting to restart");
- }
-
- return 0;
-}
-
-static void spmt_os2_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- one_process = !!ap_exists_config_define("ONE_PROCESS");
-
- is_graceful = 0;
- ap_listen_pre_config();
- ap_daemons_to_start = DEFAULT_START_DAEMON;
- ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
- ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
- ap_daemons_limit = HARD_THREAD_LIMIT;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
- ap_extended_status = 0;
- ap_scoreboard_fname = NULL;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-}
-
-static void spmt_os2_hooks(apr_pool_t *p)
-{
- /* TODO: set one_process properly */ one_process = 0;
-
- ap_hook_pre_config(spmt_os2_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in <VirtualHost>";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_to_start = atoi(arg);
- return NULL;
-}
-
-static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_min_free = atoi(arg);
- if (ap_daemons_min_free <= 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareServers set to non-positive.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Resetting to 1 to avoid almost certain Apache failure.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Please read the documentation.");
- ap_daemons_min_free = 1;
- }
-
- return NULL;
-}
-
-static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_max_free = atoi(arg);
- return NULL;
-}
-
-static const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_limit = atoi(arg);
- if (ap_daemons_limit > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: MaxClients of %d exceeds compile time limit "
- "of %d servers,", ap_daemons_limit, HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering MaxClients to %d. To increase, please "
- "see the", HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_THREAD_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- ap_daemons_limit = HARD_THREAD_LIMIT;
- }
- else if (ap_daemons_limit < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require MaxClients > 0, setting to 1");
- ap_daemons_limit = 1;
- }
- return NULL;
-}
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_max_requests_per_child = atoi(arg);
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-/* Stub functions until this MPM supports the connection status API */
-
-AP_DECLARE(void) ap_update_connection_status(long conn_id, const char *key, \
- const char *value)
-{
- /* NOP */
-}
-
-AP_DECLARE(void) ap_reset_connection_status(long conn_id)
-{
- /* NOP */
-}
-
-static const command_rec spmt_os2_cmds[] = {
-LISTEN_COMMANDS
-{ "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
- "A file for logging the server process ID"},
-{ "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
- "Number of child processes launched at server startup" },
-{ "MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, TAKE1,
- "Minimum number of idle children, to handle request spikes" },
-{ "MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1,
- "Maximum number of idle children" },
-{ "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
- "Maximum number of children alive at the same time" },
-{ "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
- "Maximum number of requests a particular child serves before dying." },
-{ "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
- "The location of the directory Apache changes to before dumping core" },
-{ NULL }
-};
-
-module AP_MODULE_DECLARE_DATA mpm_spmt_os2_module = {
- MPM20_MODULE_STUFF,
- NULL, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- spmt_os2_cmds, /* command apr_table_t */
- spmt_os2_hooks, /* register_hooks */
-};
diff --git a/server/mpm/threaded/.cvsignore b/server/mpm/threaded/.cvsignore
deleted file mode 100644
index 84df257214..0000000000
--- a/server/mpm/threaded/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.deps
-.libs
-*.lo
-*.la
-Makefile
diff --git a/server/mpm/threaded/Makefile.in b/server/mpm/threaded/Makefile.in
deleted file mode 100644
index b5fb3691a6..0000000000
--- a/server/mpm/threaded/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-LTLIBRARY_NAME = libthreaded.la
-LTLIBRARY_SOURCES = threaded.c
-
-include $(top_srcdir)/build/ltlib.mk
diff --git a/server/mpm/threaded/config5.m4 b/server/mpm/threaded/config5.m4
deleted file mode 100644
index dbc00cbf72..0000000000
--- a/server/mpm/threaded/config5.m4
+++ /dev/null
@@ -1,5 +0,0 @@
-dnl ## XXX - Need a more thorough check of the proper flags to use
-
-if test "$MPM_NAME" = "threaded" ; then
- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile)
-fi
diff --git a/server/mpm/threaded/mpm.h b/server/mpm/threaded/mpm.h
deleted file mode 100644
index 3359f8cca5..0000000000
--- a/server/mpm/threaded/mpm.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-#include "scoreboard.h"
-#include "unixd.h"
-
-#ifndef APACHE_MPM_THREADED_H
-#define APACHE_MPM_THREADED_H
-
-#define THREADED_MPM
-
-#define MPM_NAME "Threaded"
-
-#define AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES 1
-#define MPM_SYNC_CHILD_TABLE() (ap_sync_scoreboard_image())
-#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-
-extern int ap_threads_per_child;
-extern int ap_max_requests_per_child;
-extern int ap_max_daemons_limit;
-extern server_rec *ap_server_conf;
-extern char ap_coredump_dir[MAX_STRING_LEN];
-
-#endif /* APACHE_MPM_THREADED_H */
diff --git a/server/mpm/threaded/mpm_default.h b/server/mpm/threaded/mpm_default.h
deleted file mode 100644
index 84c1304bfa..0000000000
--- a/server/mpm/threaded/mpm_default.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-#define AP_ID_FROM_CHILD_THREAD(c, t) ((c * HARD_THREAD_LIMIT) + t)
-#define AP_CHILD_THREAD_FROM_ID(i) (i / HARD_THREAD_LIMIT), (i % HARD_THREAD_LIMIT)
-
-/* Number of servers to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_DAEMON
-#define DEFAULT_START_DAEMON 3
-#endif
-
-/* Maximum number of *free* server processes --- more than this, and
- * they will die off.
- */
-
-#ifndef DEFAULT_MAX_FREE_DAEMON
-#define DEFAULT_MAX_FREE_DAEMON 10
-#endif
-
-/* Minimum --- fewer than this, and more will be created */
-
-#ifndef DEFAULT_MIN_FREE_DAEMON
-#define DEFAULT_MIN_FREE_DAEMON 3
-#endif
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifdef NO_THREADS
-#define HARD_SERVER_LIMIT 256
-#endif
-#ifndef HARD_SERVER_LIMIT
-#define HARD_SERVER_LIMIT 8
-#endif
-
-/* Limit on the threads per process. Clients will be locked out if more than
- * this * HARD_SERVER_LIMIT are needed.
- *
- * We keep this for one reason it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifdef NO_THREADS
-#define HARD_THREAD_LIMIT 1
-#endif
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 64
-#endif
-
-#ifdef NO_THREADS
-#define DEFAULT_THREADS_PER_CHILD 1
-#endif
-#ifndef DEFAULT_THREADS_PER_CHILD
-#define DEFAULT_THREADS_PER_CHILD 25
-#endif
-
-/* File used for accept locking, when we use a file */
-#ifndef DEFAULT_LOCKFILE
-#define DEFAULT_LOCKFILE "logs/accept.lock"
-#endif
-
-/* Scoreboard file, if there is one */
-#ifndef DEFAULT_SCOREBOARD
-#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
-#endif
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/threaded/threaded.c b/server/mpm/threaded/threaded.c
deleted file mode 100644
index 05e29a781b..0000000000
--- a/server/mpm/threaded/threaded.c
+++ /dev/null
@@ -1,1450 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_portable.h"
-#include "apr_strings.h"
-#include "apr_file_io.h"
-#include "apr_thread_proc.h"
-#include "apr_signal.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if APR_HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#if !APR_HAS_THREADS
-#error The threaded MPM requires APR threads, but they are unavailable.
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h" /* for read_config */
-#include "http_core.h" /* for get_remote_host */
-#include "http_connection.h"
-#include "ap_mpm.h"
-#include "unixd.h"
-#include "mpm_common.h"
-#include "ap_listen.h"
-#include "scoreboard.h"
-
-#include <signal.h>
-#include <limits.h> /* for INT_MAX */
-
-/*
- * Actual definitions of config globals
- */
-
-int ap_threads_per_child=0; /* Worker threads per child */
-int ap_max_requests_per_child=0;
-static const char *ap_pid_fname=NULL;
-static int ap_daemons_to_start=0;
-static int min_spare_threads=0;
-static int max_spare_threads=0;
-static int ap_daemons_limit=0;
-static int workers_may_exit = 0;
-static int requests_this_child;
-static int num_listensocks = 0;
-static apr_socket_t **listensocks;
-
-/* The structure used to pass unique initialization info to each thread */
-typedef struct {
- int pid;
- int tid;
- int sd;
- apr_pool_t *tpool; /* "pthread" would be confusing */
-} proc_info;
-
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across SIGWINCH restarts. We use this
- * value to optimize routines that have to scan the entire scoreboard.
- */
-int ap_max_daemons_limit = -1;
-
-char ap_coredump_dir[MAX_STRING_LEN];
-
-static apr_file_t *pipe_of_death_in = NULL;
-static apr_file_t *pipe_of_death_out = NULL;
-static apr_lock_t *pipe_of_death_mutex; /* insures that a child process only
- consumes one character */
-
-/* *Non*-shared http_main globals... */
-
-server_rec *ap_server_conf;
-
-/* one_process --- debugging mode variable; can be set from the command line
- * with the -X flag. If set, this gets you the child_main loop running
- * in the process which originally started up (no detach, no make_child),
- * which is a pretty nice debugging environment. (You'll get a SIGHUP
- * early in standalone_main; just continue through. This is the server
- * trying to kill off any child processes which it might have lying
- * around --- Apache doesn't keep track of their pids, it just sends
- * SIGHUP to the process group, ignoring it in the root process.
- * Continue through and you'll be fine.).
- */
-
-static int one_process = 0;
-
-#ifdef DEBUG_SIGSTOP
-int raise_sigstop_flags;
-#endif
-
-static apr_pool_t *pconf; /* Pool for config stuff */
-static apr_pool_t *pchild; /* Pool for httpd child stuff */
-
-static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
- thread. Use this instead */
-/* Keep track of the number of worker threads currently active */
-static int worker_thread_count;
-static apr_lock_t *worker_thread_count_mutex;
-
-/* Locks for accept serialization */
-static apr_lock_t *accept_mutex;
-static const char *lock_fname;
-
-#ifdef NO_SERIALIZED_ACCEPT
-#define SAFE_ACCEPT(stmt) APR_SUCCESS
-#else
-#define SAFE_ACCEPT(stmt) (stmt)
-#endif
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = ap_max_daemons_limit;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_STATIC;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_DYNAMIC;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = ap_threads_per_child;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-/* a clean exit from a child with proper cleanup */
-static void clean_child_exit(int code) __attribute__ ((noreturn));
-static void clean_child_exit(int code)
-{
- if (pchild) {
- apr_pool_destroy(pchild);
- }
- exit(code);
-}
-
-/* handle all varieties of core dumping signals */
-static void sig_coredump(int sig)
-{
- chdir(ap_coredump_dir);
- apr_signal(sig, SIG_DFL);
- kill(ap_my_pid, sig);
- /* At this point we've got sig blocked, because we're still inside
- * the signal handler. When we leave the signal handler it will
- * be unblocked, and we'll take the signal... and coredump or whatever
- * is appropriate for this particular Unix. In addition the parent
- * will see the real signal we received -- whereas if we called
- * abort() here, the parent would only see SIGABRT.
- */
-}
-
-static void just_die(int sig)
-{
- clean_child_exit(0);
-}
-
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-ap_generation_t volatile ap_my_generation;
-
-/*
- * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
- * functions to initiate shutdown or restart without relying on signals.
- * Previously this was initiated in sig_term() and restart() signal handlers,
- * but we want to be able to start a shutdown/restart from other sources --
- * e.g. on Win32, from the service manager. Now the service manager can
- * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
- * these functions can also be called by the child processes, since global
- * variables are no longer used to pass on the required action to the parent.
- *
- * These should only be called from the parent process itself, since the
- * parent process will use the shutdown_pending and restart_pending variables
- * to determine whether to shutdown or restart. The child process should
- * call signal_parent() directly to tell the parent to die -- this will
- * cause neither of those variable to be set, which the parent will
- * assume means something serious is wrong (which it will be, for the
- * child to force an exit) and so do an exit anyway.
- */
-
-static void ap_start_shutdown(void)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-/* do a graceful restart if graceful == 1 */
-static void ap_start_restart(int graceful)
-{
-
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- is_graceful = graceful;
- if (is_graceful) {
- apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
- }
-}
-
-static void sig_term(int sig)
-{
- ap_start_shutdown();
-}
-
-static void restart(int sig)
-{
- ap_start_restart(sig == SIGWINCH);
-}
-
-static void set_signals(void)
-{
-#ifndef NO_USE_SIGACTION
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
- if (!one_process) {
- sa.sa_handler = sig_coredump;
-#if defined(SA_ONESHOT)
- sa.sa_flags = SA_ONESHOT;
-#elif defined(SA_RESETHAND)
- sa.sa_flags = SA_RESETHAND;
-#endif
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
-#ifdef SIGBUS
- if (sigaction(SIGBUS, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
-#endif
-#ifdef SIGABORT
- if (sigaction(SIGABORT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
-#endif
-#ifdef SIGABRT
- if (sigaction(SIGABRT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
-#endif
-#ifdef SIGILL
- if (sigaction(SIGILL, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
-#endif
- sa.sa_flags = 0;
- }
- sa.sa_handler = sig_term;
- if (sigaction(SIGTERM, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
-#ifdef SIGINT
- if (sigaction(SIGINT, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
-#endif
-#ifdef SIGXCPU
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXCPU, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
-#endif
-#ifdef SIGXFSZ
- sa.sa_handler = SIG_DFL;
- if (sigaction(SIGXFSZ, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
-#endif
-#ifdef SIGPIPE
- sa.sa_handler = SIG_IGN;
- if (sigaction(SIGPIPE, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
-#endif
-
- /* we want to ignore HUPs and WINCH while we're busy processing one */
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sa.sa_handler = restart;
- if (sigaction(SIGHUP, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
- if (sigaction(SIGWINCH, &sa, NULL) < 0)
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
-#else
- if (!one_process) {
- apr_signal(SIGSEGV, sig_coredump);
-#ifdef SIGBUS
- apr_signal(SIGBUS, sig_coredump);
-#endif /* SIGBUS */
-#ifdef SIGABORT
- apr_signal(SIGABORT, sig_coredump);
-#endif /* SIGABORT */
-#ifdef SIGABRT
- apr_signal(SIGABRT, sig_coredump);
-#endif /* SIGABRT */
-#ifdef SIGILL
- apr_signal(SIGILL, sig_coredump);
-#endif /* SIGILL */
-#ifdef SIGXCPU
- apr_signal(SIGXCPU, SIG_DFL);
-#endif /* SIGXCPU */
-#ifdef SIGXFSZ
- apr_signal(SIGXFSZ, SIG_DFL);
-#endif /* SIGXFSZ */
- }
-
- apr_signal(SIGTERM, sig_term);
-#ifdef SIGHUP
- apr_signal(SIGHUP, restart);
-#endif /* SIGHUP */
-#ifdef SIGWINCH
- apr_signal(SIGWINCH, restart);
-#endif /* SIGWINCH */
-#ifdef SIGPIPE
- apr_signal(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
-
-#endif
-}
-
-/*****************************************************************
- * Here follows a long bunch of generic server bookkeeping stuff...
- */
-
-int ap_graceful_stop_signalled(void)
-{
- /* XXX - Does this really work? - Manoj */
- return is_graceful;
-}
-
-/*****************************************************************
- * Child process main loop.
- */
-
-static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num, int my_thread_num)
-{
- conn_rec *current_conn;
- long conn_id = AP_ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
- int csd;
-
- (void) apr_os_sock_get(&csd, sock);
-
- if (csd >= FD_SETSIZE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
- "new file descriptor %d is too large; you probably need "
- "to rebuild Apache with a larger FD_SETSIZE "
- "(currently %d)",
- csd, FD_SETSIZE);
- apr_socket_close(sock);
- return;
- }
-
- ap_sock_disable_nagle(sock);
-
- current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id);
- if (current_conn) {
- ap_process_connection(current_conn);
- ap_lingering_close(current_conn);
- }
-}
-/* Sets workers_may_exit if we received a character on the pipe_of_death */
-static void check_pipe_of_death(void)
-{
- apr_lock_acquire(pipe_of_death_mutex);
- if (!workers_may_exit) {
- apr_status_t ret;
- char pipe_read_char;
- apr_size_t n = 1;
-
- ret = apr_recv(listensocks[0], &pipe_read_char, &n);
- if (APR_STATUS_IS_EAGAIN(ret)) {
- /* It lost the lottery. It must continue to suffer
- * through a life of servitude. */
- }
- else {
- /* It won the lottery (or something else is very
- * wrong). Embrace death with open arms. */
- workers_may_exit = 1;
- }
- }
- apr_lock_release(pipe_of_death_mutex);
-}
-
-static void * worker_thread(void * dummy)
-{
- proc_info * ti = dummy;
- int process_slot = ti->pid;
- int thread_slot = ti->tid;
- apr_pool_t *tpool = ti->tpool;
- apr_socket_t *csd = NULL;
- apr_pool_t *ptrans; /* Pool for per-transaction stuff */
- apr_socket_t *sd = NULL;
- int n;
- int curr_pollfd, last_pollfd = 0;
- apr_pollfd_t *pollset;
- apr_status_t rv;
-
- free(ti);
-
- apr_pool_create(&ptrans, tpool);
-
- apr_lock_acquire(worker_thread_count_mutex);
- worker_thread_count++;
- apr_lock_release(worker_thread_count_mutex);
-
- apr_poll_setup(&pollset, num_listensocks+1, tpool);
- for(n=0 ; n <= num_listensocks ; ++n)
- apr_poll_socket_add(pollset, listensocks[n], APR_POLLIN);
-
- /* TODO: Switch to a system where threads reuse the results from earlier
- poll calls - manoj */
- while (1) {
- workers_may_exit |= (requests_this_child <= 0);
- if (workers_may_exit) break;
-
- (void) ap_update_child_status(process_slot, thread_slot, SERVER_READY,
- (request_rec *) NULL);
- if ((rv = SAFE_ACCEPT(apr_lock_acquire(accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_acquire failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
-
- while (!workers_may_exit) {
- apr_status_t ret;
- apr_int16_t event;
-
- ret = apr_poll(pollset, &n, -1);
- if (ret != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(ret)) {
- continue;
- }
-
- /* apr_poll() will only return errors in catastrophic
- * circumstances. Let's try exiting gracefully, for now. */
- ap_log_error(APLOG_MARK, APLOG_ERR, ret, (const server_rec *)
- ap_server_conf, "apr_poll: (listen)");
- workers_may_exit = 1;
- }
-
- if (workers_may_exit) break;
-
- apr_poll_revents_get(&event, listensocks[0], pollset);
- if (event & APR_POLLIN) {
- /* A process got a signal on the shutdown pipe. Check if we're
- * the lucky process to die. */
- check_pipe_of_death();
- continue;
- }
-
- if (num_listensocks == 1) {
- sd = ap_listeners->sd;
- goto got_fd;
- }
- else {
- /* find a listener */
- curr_pollfd = last_pollfd;
- do {
- curr_pollfd++;
- if (curr_pollfd > num_listensocks) {
- curr_pollfd = 1;
- }
- /* XXX: Should we check for POLLERR? */
- apr_poll_revents_get(&event, listensocks[curr_pollfd], pollset);
- if (event & APR_POLLIN) {
- last_pollfd = curr_pollfd;
- sd=listensocks[curr_pollfd];
- goto got_fd;
- }
- } while (curr_pollfd != last_pollfd);
- }
- }
- got_fd:
- if (!workers_may_exit) {
- if ((rv = apr_accept(&csd, sd, ptrans)) != APR_SUCCESS) {
- csd = NULL;
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
- "apr_accept");
- }
- if ((rv = SAFE_ACCEPT(apr_lock_release(accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- if (csd != NULL) {
- process_socket(ptrans, csd, process_slot, thread_slot);
- requests_this_child--;
- }
- }
- else {
- if ((rv = SAFE_ACCEPT(apr_lock_release(accept_mutex)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "apr_lock_release failed. Attempting to shutdown "
- "process gracefully.");
- workers_may_exit = 1;
- }
- break;
- }
- apr_pool_clear(ptrans);
- }
-
- apr_pool_destroy(tpool);
- ap_update_child_status(process_slot, thread_slot, SERVER_DEAD,
- (request_rec *) NULL);
- apr_lock_acquire(worker_thread_count_mutex);
- worker_thread_count--;
- if (worker_thread_count == 0) {
- /* All the threads have exited, now finish the shutdown process
- * by signalling the sigwait thread */
- kill(ap_my_pid, SIGTERM);
- }
- apr_lock_release(worker_thread_count_mutex);
-
- return NULL;
-}
-
-static int check_signal(int signum)
-{
- switch (signum) {
- case SIGTERM:
- case SIGINT:
- return 1;
- }
- return 0;
-}
-
-static void child_main(int child_num_arg)
-{
- apr_thread_t **threads;
- apr_threadattr_t *thread_attr;
- int i;
- int my_child_num = child_num_arg;
- proc_info *my_info = NULL;
- ap_listen_rec *lr;
- apr_status_t rv;
-
-
- ap_my_pid = getpid();
- apr_pool_create(&pchild, pconf);
-
- /*stuff to do before we switch id's, so we have permissions.*/
- reopen_scoreboard(pchild);
-
- rv = SAFE_ACCEPT(apr_lock_child_init(&accept_mutex, lock_fname,
- pchild));
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "Couldn't initialize cross-process lock in child");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- if (unixd_setup_child()) {
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- ap_run_child_init(pchild, ap_server_conf);
-
- /*done with init critical section */
-
- rv = apr_setup_signal_thread();
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
- "Couldn't initialize signal thread");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
-
- requests_this_child = ap_max_requests_per_child;
-
- /* Set up the pollfd array */
- listensocks = apr_pcalloc(pchild,
- sizeof(*listensocks) * (num_listensocks + 1));
-#if APR_FILES_AS_SOCKETS
- apr_socket_from_file(&listensocks[0], pipe_of_death_in);
-#endif
- for (lr = ap_listeners, i = 1; i <= num_listensocks; lr = lr->next, ++i)
- listensocks[i]=lr->sd;
-
- /* Setup worker threads */
-
- threads = (apr_thread_t **)malloc(sizeof(apr_thread_t *) * ap_threads_per_child);
- if (threads == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
- "malloc: out of memory");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
- worker_thread_count = 0;
- apr_lock_create(&worker_thread_count_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_lock_create(&pipe_of_death_mutex, APR_MUTEX, APR_INTRAPROCESS,
- NULL, pchild);
- apr_threadattr_create(&thread_attr, pchild);
- apr_threadattr_detach_set(thread_attr, 0); /* 0 means PTHREAD_CREATE_JOINABLE */
-
- for (i=0; i < ap_threads_per_child; i++) {
-
- my_info = (proc_info *)malloc(sizeof(proc_info));
- if (my_info == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
- "malloc: out of memory");
- clean_child_exit(APEXIT_CHILDFATAL);
- }
- my_info->pid = my_child_num;
- my_info->tid = i;
- my_info->sd = 0;
- apr_pool_create(&my_info->tpool, pchild);
-
- /* We are creating threads right now */
- (void) ap_update_child_status(my_child_num, i, SERVER_STARTING,
- (request_rec *) NULL);
- if ((rv = apr_thread_create(&threads[i], thread_attr, worker_thread, my_info, pchild))) {
- ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
- "apr_thread_create: unable to create worker thread");
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again if we exit. */
- sleep(10);
- clean_child_exit(APEXIT_CHILDFATAL);
- }
- /* We let each thread update it's own scoreboard entry. This is done
- * because it let's us deal with tid better.
- */
- }
-
- /* What state should this child_main process be listed as in the scoreboard...?
- * ap_update_child_status(my_child_num, i, SERVER_STARTING, (request_rec *) NULL);
- *
- * This state should be listed separately in the scoreboard, in some kind
- * of process_status, not mixed in with the worker threads' status.
- * "life_status" is almost right, but it's in the worker's structure, and
- * the name could be clearer. gla
- */
-
- apr_signal_thread(check_signal);
-
- workers_may_exit = 1; /* helps us terminate a little more quickly when
- * the dispatch of the signal thread
- * beats the Pipe of Death and the browsers
- */
-
- /* A terminating signal was received. Now join each of the workers to clean them up.
- * If the worker already exited, then the join frees their resources and returns.
- * If the worker hasn't exited, then this blocks until they have (then cleans up).
- */
- for (i = 0; i < ap_threads_per_child; i++) {
- apr_thread_join(&rv, threads[i]);
- }
-
- free (threads);
-
- clean_child_exit(0);
-}
-
-static int make_child(server_rec *s, int slot)
-{
- int pid;
-
- if (slot + 1 > ap_max_daemons_limit) {
- ap_max_daemons_limit = slot + 1;
- }
-
- if (one_process) {
- set_signals();
- ap_scoreboard_image->parent[slot].pid = getpid();
- child_main(slot);
- }
-
- /* Tag this slot as occupied so that perform_idle_server_maintenance
- * doesn't try to steal it */
- (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
-
- if ((pid = fork()) == -1) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
-
- /* fork didn't succeed. Fix the scoreboard or else
- * it will say SERVER_STARTING forever and ever
- */
- (void) ap_update_child_status(slot, 0, SERVER_DEAD, (request_rec *) NULL);
-
- /* In case system resources are maxxed out, we don't want
- Apache running away with the CPU trying to fork over and
- over and over again. */
- sleep(10);
-
- return -1;
- }
-
- if (!pid) {
-#ifdef AIX_BIND_PROCESSOR
- /* By default, AIX binds to a single processor. This bit unbinds
- children which will then bind to another CPU.
- */
-#include <sys/processor.h>
- int status = bindprocessor(BINDPROCESS, (int)getpid(),
- PROCESSOR_CLASS_ANY);
- if (status != OK)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, ap_server_conf,
- "processor unbind failed %d", status);
-#endif
-
- RAISE_SIGSTOP(MAKE_CHILD);
-
- apr_signal(SIGTERM, just_die);
- child_main(slot);
-
- clean_child_exit(0);
- }
- /* else */
- ap_scoreboard_image->parent[slot].pid = pid;
- return 0;
-}
-
-/* If there aren't many connections coming in from the network, the child
- * processes may need to be awakened from their network i/o waits.
- * The pipe of death is an effective prod.
- */
-
-static void wake_up_and_die(void)
-{
- int i;
- char char_of_death = '!';
- apr_size_t one = 1;
- apr_status_t rv;
-
- for (i = 0; i < ap_daemons_limit;) {
- if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one))
- != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(rv)) continue;
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
- "write pipe_of_death");
- }
- i++;
- }
-}
-
-/* start up a bunch of children */
-static void startup_children(int number_to_start)
-{
- int i;
-
- for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
- if (ap_scoreboard_image->parent[i].pid != 0) {
- continue;
- }
- if (make_child(ap_server_conf, i) < 0) {
- break;
- }
- --number_to_start;
- }
-}
-
-
-/*
- * idle_spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int idle_spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
-static void perform_idle_server_maintenance(void)
-{
- int i, j;
- int idle_thread_count;
- short_score *ss;
- int free_length;
- int free_slots[MAX_SPAWN_RATE];
- int last_non_dead;
- int total_non_dead;
- apr_size_t one = 1;
- apr_status_t rv;
-
- /* initialize the free_list */
- free_length = 0;
-
- idle_thread_count = 0;
- last_non_dead = -1;
- total_non_dead = 0;
-
- ap_sync_scoreboard_image();
- for (i = 0; i < ap_daemons_limit; ++i) {
- /* Initialization to satisfy the compiler. It doesn't know
- * that ap_threads_per_child is always > 0 */
- int status = SERVER_DEAD;
- int any_dying_threads = 0;
- int all_dead_threads = 1;
- int idle_thread_addition = 0;
-
- if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
- break;
- for (j = 0; j < ap_threads_per_child; j++) {
- ss = &ap_scoreboard_image->servers[i][j];
- status = ss->status;
-
- any_dying_threads = any_dying_threads || (status == SERVER_DEAD)
- || (status == SERVER_GRACEFUL);
- all_dead_threads = all_dead_threads && (status == SERVER_DEAD);
-
- /* We consider a starting server as idle because we started it
- * at least a cycle ago, and if it still hasn't finished starting
- * then we're just going to swamp things worse by forking more.
- * So we hopefully won't need to fork more if we count it.
- * This depends on the ordering of SERVER_READY and SERVER_STARTING.
- */
- if (status <= SERVER_READY) {
- ++idle_thread_addition;
- }
- }
- if (all_dead_threads && free_length < idle_spawn_rate) {
- free_slots[free_length] = i;
- ++free_length;
- }
- if (!all_dead_threads) {
- last_non_dead = i;
- }
- if (!any_dying_threads) {
- ++total_non_dead;
- idle_thread_count += idle_thread_addition;
- }
- }
- ap_max_daemons_limit = last_non_dead + 1;
-
- if (idle_thread_count > max_spare_threads) {
- /* Kill off one child */
- char char_of_death = '!';
- if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, "write pipe_of_death");
- }
- idle_spawn_rate = 1;
- }
- else if (idle_thread_count < min_spare_threads) {
- /* terminate the free list */
- if (free_length == 0) {
- /* only report this condition once */
- static int reported = 0;
-
- if (!reported) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
- "server reached MaxClients setting, consider"
- " raising the MaxClients setting");
- reported = 1;
- }
- idle_spawn_rate = 1;
- }
- else {
-
- if (idle_spawn_rate >= 8) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "server seems busy, (you may need "
- "to increase StartServers, ThreadsPerChild "
- "or Min/MaxSpareThreads), "
- "spawning %d children, there are around %d idle "
- "threads, and %d total children", idle_spawn_rate,
- idle_thread_count, total_non_dead);
- }
- for (i = 0; i < free_length; ++i) {
- make_child(ap_server_conf, free_slots[i]);
- }
- /* the next time around we want to spawn twice as many if this
- * wasn't good enough, but not if we've just done a graceful
- */
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
- }
- else if (idle_spawn_rate < MAX_SPAWN_RATE) {
- idle_spawn_rate *= 2;
- }
- }
- }
- else {
- idle_spawn_rate = 1;
- }
-}
-
-static void server_main_loop(int remaining_children_to_start)
-{
- int child_slot;
- apr_wait_t status;
- apr_proc_t pid;
- int i;
-
- while (!restart_pending && !shutdown_pending) {
- ap_wait_or_timeout(&status, &pid, pconf);
-
- if (pid.pid != -1) {
- ap_process_child_status(&pid, status);
- /* non-fatal death... note that it's gone in the scoreboard. */
- child_slot = find_child_by_pid(&pid);
- if (child_slot >= 0) {
- for (i = 0; i < ap_threads_per_child; i++)
- ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
-
- if (remaining_children_to_start
- && child_slot < ap_daemons_limit) {
- /* we're still doing a 1-for-1 replacement of dead
- * children with new children
- */
- make_child(ap_server_conf, child_slot);
- --remaining_children_to_start;
- }
-#if APR_HAS_OTHER_CHILD
- }
- else if (apr_proc_other_child_read(&pid, status) == 0) {
- /* handled */
-#endif
- }
- else if (is_graceful) {
- /* Great, we've probably just lost a slot in the
- * scoreboard. Somehow we don't know about this child.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0,
- ap_server_conf,
- "long lost child came home! (pid %ld)",
- (long)pid.pid);
- }
- /* Don't perform idle maintenance when a child dies,
- * only do it when there's a timeout. Remember only a
- * finite number of children can die, and it's pretty
- * pathological for a lot to die suddenly.
- */
- continue;
- }
- else if (remaining_children_to_start) {
- /* we hit a 1 second timeout in which none of the previous
- * generation of children needed to be reaped... so assume
- * they're all done, and pick up the slack if any is left.
- */
- startup_children(remaining_children_to_start);
- remaining_children_to_start = 0;
- /* In any event we really shouldn't do the code below because
- * few of the servers we just started are in the IDLE state
- * yet, so we'd mistakenly create an extra server.
- */
- continue;
- }
-
- perform_idle_server_maintenance();
- }
-}
-
-int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
-{
- int remaining_children_to_start;
- apr_status_t rv;
-
- pconf = _pconf;
- ap_server_conf = s;
- rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out, pconf);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_create (pipe_of_death)");
- exit(1);
- }
-
- if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv,
- (const server_rec*) ap_server_conf,
- "apr_file_pipe_timeout_set (pipe_of_death)");
- exit(1);
- }
- ap_server_conf = s;
- if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
- /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
- "no listening sockets available, shutting down");
- return 1;
- }
- ap_log_pid(pconf, ap_pid_fname);
-
- /* Initialize cross-process accept lock */
- lock_fname = apr_psprintf(_pconf, "%s.%" APR_OS_PROC_T_FMT,
- ap_server_root_relative(_pconf, lock_fname),
- ap_my_pid);
- rv = apr_lock_create(&accept_mutex, APR_MUTEX, APR_LOCKALL,
- lock_fname, _pconf);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
- "Couldn't create accept lock");
- return 1;
- }
-
-
- if (!is_graceful) {
- ap_create_scoreboard(pconf, SB_SHARED);
- }
-
- set_signals();
- /* Don't thrash... */
- if (max_spare_threads < min_spare_threads + ap_threads_per_child)
- max_spare_threads = min_spare_threads + ap_threads_per_child;
-
- /* If we're doing a graceful_restart then we're going to see a lot
- * of children exiting immediately when we get into the main loop
- * below (because we just sent them SIGWINCH). This happens pretty
- * rapidly... and for each one that exits we'll start a new one until
- * we reach at least daemons_min_free. But we may be permitted to
- * start more than that, so we'll just keep track of how many we're
- * supposed to start up without the 1 second penalty between each fork.
- */
- remaining_children_to_start = ap_daemons_to_start;
- if (remaining_children_to_start > ap_daemons_limit) {
- remaining_children_to_start = ap_daemons_limit;
- }
- if (!is_graceful) {
- startup_children(remaining_children_to_start);
- remaining_children_to_start = 0;
- }
- else {
- /* give the system some time to recover before kicking into
- * exponential mode */
- hold_off_on_exponential_spawning = 10;
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "%s configured -- resuming normal operations",
- ap_get_server_version());
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
- "Server built: %s", ap_get_server_built());
- restart_pending = shutdown_pending = 0;
-
- server_main_loop(remaining_children_to_start);
-
- if (shutdown_pending) {
- /* Time to gracefully shut down:
- * Kill child processes, tell them to call child_exit, etc...
- */
- wake_up_and_die();
-
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
-
- /* cleanup pid file on normal shutdown */
- {
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
- ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "caught SIGTERM, shutting down");
-
- return 1;
- }
-
- /* we've been told to restart */
- apr_signal(SIGHUP, SIG_IGN);
-
- if (one_process) {
- /* not worth thinking about */
- return 1;
- }
-
- /* advance to the next generation */
- /* XXX: we really need to make sure this new generation number isn't in
- * use by any of the children.
- */
- ++ap_my_generation;
- ap_scoreboard_image->global.running_generation = ap_my_generation;
- update_scoreboard_global();
-
- /* wake up the children...time to die. But we'll have more soon */
- wake_up_and_die();
-
- if (is_graceful) {
- int i, j;
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGWINCH received. Doing graceful restart");
-
- /* This is mostly for debugging... so that we know what is still
- * gracefully dealing with existing request.
- */
-
- for (i = 0; i < ap_daemons_limit; ++i) {
- for (j = 0; j < ap_threads_per_child; j++) {
- if (ap_scoreboard_image->servers[i][j].status != SERVER_DEAD) {
- ap_scoreboard_image->servers[i][j].status = SERVER_GRACEFUL;
- }
- }
- }
- }
- else {
- /* Kill 'em all. Since the child acts the same on the parents SIGTERM
- * and a SIGHUP, we may as well use the same signal, because some user
- * pthreads are stealing signals from us left and right.
- */
- if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
- }
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
- "SIGHUP received. Attempting to restart");
- }
- return 0;
-}
-
-static void threaded_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- static int restart_num = 0;
- int no_detach = 0;
-
- one_process = !!ap_exists_config_define("ONE_PROCESS");
- no_detach = !!ap_exists_config_define("NO_DETACH");
-
- /* sigh, want this only the second time around */
- if (restart_num++ == 1) {
- is_graceful = 0;
-
- if (!one_process && !no_detach) {
- apr_proc_detach();
- }
- ap_my_pid = getpid();
- }
-
- unixd_pre_config(ptemp);
- ap_listen_pre_config();
- ap_daemons_to_start = DEFAULT_START_DAEMON;
- min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
- max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
- ap_daemons_limit = HARD_SERVER_LIMIT;
- ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_scoreboard_fname = DEFAULT_SCOREBOARD;
- lock_fname = DEFAULT_LOCKFILE;
- ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
- ap_extended_status = 0;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-}
-
-static void threaded_hooks(apr_pool_t *p)
-{
- one_process = 0;
-
- ap_hook_pre_config(threaded_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in <VirtualHost>";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_scoreboard(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_scoreboard_fname = arg;
- return NULL;
-}
-
-static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- lock_fname = arg;
- return NULL;
-}
-
-static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_to_start = atoi(arg);
- return NULL;
-}
-
-static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- min_spare_threads = atoi(arg);
- if (min_spare_threads <= 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: detected MinSpareThreads set to non-positive.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Resetting to 1 to avoid almost certain Apache failure.");
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Please read the documentation.");
- min_spare_threads = 1;
- }
-
- return NULL;
-}
-
-static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- max_spare_threads = atoi(arg);
- return NULL;
-}
-
-static const char *set_server_limit (cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_daemons_limit = atoi(arg);
- if (ap_daemons_limit > HARD_SERVER_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: MaxClients of %d exceeds compile time limit "
- "of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering MaxClients to %d. To increase, please "
- "see the", HARD_SERVER_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_SERVER_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- ap_daemons_limit = HARD_SERVER_LIMIT;
- }
- else if (ap_daemons_limit < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: Require MaxClients > 0, setting to 1");
- ap_daemons_limit = 1;
- }
- return NULL;
-}
-
-static const char *set_threads_per_child (cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_threads_per_child = atoi(arg);
- if (ap_threads_per_child > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: ThreadsPerChild of %d exceeds compile time"
- "limit of %d threads,", ap_threads_per_child,
- HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering ThreadsPerChild to %d. To increase, please"
- " see the", HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " HARD_THREAD_LIMIT define in %s.",
- AP_MPM_HARD_LIMITS_FILE);
- }
- else if (ap_threads_per_child < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require ThreadsPerChild > 0, setting to 1");
- ap_threads_per_child = 1;
- }
- return NULL;
-}
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_max_requests_per_child = atoi(arg);
-
- /* a value of zero means infinity. The following removes a conditional
- * from worker_thread's hot path
- */
-
- if (!ap_max_requests_per_child) {
- ap_max_requests_per_child = INT_MAX;
- }
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-static const command_rec threaded_cmds[] = {
-UNIX_DAEMON_COMMANDS
-LISTEN_COMMANDS
-AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
- "A file for logging the server process ID"),
-AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
- "A file for Apache to maintain runtime process management information"),
-AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
- "The lockfile used when Apache needs to lock the accept() call"),
-AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
- "Number of child processes launched at server startup"),
-AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
- "Minimum number of idle children, to handle request spikes"),
-AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
- "Maximum number of idle children"),
-AP_INIT_TAKE1("MaxClients", set_server_limit, NULL, RSRC_CONF,
- "Maximum number of children alive at the same time"),
-AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
- "Number of threads each child creates"),
-AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
- "Maximum number of requests a particular child serves before dying."),
-AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
- "The location of the directory Apache changes to before dumping core"),
-{ NULL }
-};
-
-module AP_MODULE_DECLARE_DATA mpm_threaded_module = {
- MPM20_MODULE_STUFF,
- NULL, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- threaded_cmds, /* command apr_table_t */
- threaded_hooks /* register_hooks */
-};
-
diff --git a/server/mpm/winnt/Win9xConHook.c b/server/mpm/winnt/Win9xConHook.c
deleted file mode 100644
index a285329b43..0000000000
--- a/server/mpm/winnt/Win9xConHook.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifdef WIN32
-
-/*
- * Win9xConHook.dll - a hook proc to clean up Win95/98 console behavior.
- *
- * It is well(?) documented by Microsoft that the Win9x HandlerRoutine
- * hooked by the SetConsoleCtrlHandler never receives the CTRL_CLOSE_EVENT,
- * CTRL_LOGOFF_EVENT or CTRL_SHUTDOWN_EVENT signals.
- *
- * It is possible to have a second window to monitor the WM_ENDSESSION
- * message, but the close button still fails..
- *
- * There is a 16bit polling method for the close window option, but this
- * is CPU intensive and requires thunking.
- *
- * Attempts to subclass the 'tty' console fail, since that message thread
- * is actually owned by the 16 bit winoldap.mod process, although the
- * window reports it is owned by the process/thread of the console app.
- *
- * Win9xConHook is thunks the WM_CLOSE and WM_ENDSESSION messages,
- * first through a window hook procedure in the winoldap context, into
- * a subclass WndProc, and on to a second hidden monitor window in the
- * console application's context that dispatches them to the console app's
- * registered HandlerRoutine.
- */
-
-/* This debugging define turns on output to COM1, although you better init
- * the port first (even using hyperterm). It's the only way to catch the
- * goings on within system logoff/shutdown.
- * #define DBG 1
- */
-
-#include <windows.h>
-
-/* Variables used within any process context:
- * hookwndmsg is a shared message to send Win9xConHook signals
- * origwndprop is a wndprop atom to store the orig wndproc of the tty
- * hookwndprop is a wndprop atom to store the hwnd of the hidden child
- * is_service reminds us to unmark this process on the way out
- */
-static UINT hookwndmsg = 0;
-static LPCTSTR origwndprop;
-static LPCTSTR hookwndprop;
-static BOOL is_service = 0;
-//static HMODULE hmodThis = NULL;
-
-/* Variables used within the tty processes' context:
- * is_tty flags this process; -1 == unknown, 1 == if tty, 0 == if not
- * hw_tty is the handle of the top level tty in this process context
- * is_subclassed is toggled to assure DllMain removes the subclass on unload
- * hmodLock is there to try and prevent this dll from being unloaded if the
- * hook is removed while we are subclassed
- */
-static int is_tty = -1;
-static HWND hwtty = NULL;
-static BOOL is_subclassed = 0;
-
-// This simply causes a gpfault the moment it tries to FreeLibrary within
-// the subclass procedure ... not good.
-//static HMODULE hmodLock = NULL;
-
-/* Variables used within the service or console app's context:
- * hmodHook is the instance handle of this module for registering the hooks
- * hhkGetMessage is the hook handle for catching Posted messages
- * hhkGetMessage is the hook handle for catching Sent messages
- * monitor_hwnd is the invisible window that handles our tty messages
- * the tty_info strucure is used to pass args into the hidden window's thread
- */
-static HMODULE hmodHook = NULL;
-static HHOOK hhkGetMessage;
-//static HHOOK hhkCallWndProc;
-static HWND monitor_hwnd = NULL;
-
-typedef struct {
- PHANDLER_ROUTINE phandler;
- HINSTANCE instance;
- HWND parent;
- INT type;
- LPCSTR name;
-} tty_info;
-
-/* These are the GetWindowLong offsets for the hidden window's internal info
- * gwltty_phandler is the address of the app's HandlerRoutine
- * gwltty_ttywnd is the tty this hidden window will handle messages from
- */
-#define gwltty_phandler 0
-#define gwltty_ttywnd 4
-
-/* Forward declaration prototypes for internal functions
- */
-static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd);
-static LRESULT WINAPI RegisterWindows9xService(BOOL set_service);
-static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam);
-static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty);
-static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam);
-static int HookProc(int hc, HWND *hwnd, UINT *msg,
- WPARAM *wParam, LPARAM *lParam);
-#ifdef DBG
-static VOID DbgPrintf(LPTSTR fmt, ...);
-#endif
-
-
-/* DllMain is invoked by every process in the entire system that is hooked
- * by our window hooks, notably the tty processes' context, and by the user
- * who wants tty messages (the app). Keep it light and simple.
- */
-BOOL __declspec(dllexport) APIENTRY DllMain(HINSTANCE hModule, ULONG ulReason,
- LPVOID pctx)
-{
- if (ulReason == DLL_PROCESS_ATTACH)
- {
- //hmodThis = hModule;
- if (!hookwndmsg) {
- origwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookOrigProc"));
- hookwndprop = MAKEINTATOM(GlobalAddAtom("Win9xConHookThunkWnd"));
- hookwndmsg = RegisterWindowMessage("Win9xConHookMsg");
- }
-#ifdef DBG
-// DbgPrintf("H ProcessAttach:%8.8x\r\n",
-// GetCurrentProcessId());
-#endif
- }
- else if ( ulReason == DLL_PROCESS_DETACH )
- {
-#ifdef DBG
-// DbgPrintf("H ProcessDetach:%8.8x\r\n", GetCurrentProcessId());
-#endif
- if (monitor_hwnd)
- SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
- if (is_subclassed)
- SendMessage(hwtty, hookwndmsg, 0, (LPARAM)hwtty);
- if (hmodHook)
- {
- if (hhkGetMessage) {
- UnhookWindowsHookEx(hhkGetMessage);
- hhkGetMessage = NULL;
- }
- //if (hhkCallWndProc) {
- // UnhookWindowsHookEx(hhkCallWndProc);
- // hhkCallWndProc = NULL;
- //}
- FreeLibrary(hmodHook);
- hmodHook = NULL;
- }
- if (is_service)
- RegisterWindows9xService(FALSE);
- if (hookwndmsg) {
- GlobalDeleteAtom((ATOM)origwndprop);
- GlobalDeleteAtom((ATOM)hookwndprop);
- hookwndmsg = 0;
- }
- }
- return TRUE;
-}
-
-
-/* This group of functions are provided for the service/console app
- * to register itself a HandlerRoutine to accept tty or service messages
- */
-
-
-/* Exported function that creates a Win9x 'service' via a hidden window,
- * that notifies the process via the HandlerRoutine messages.
- */
-BOOL __declspec(dllexport) WINAPI Windows9xServiceCtrlHandler(
- PHANDLER_ROUTINE phandler,
- LPCSTR name)
-{
- /* If we have not yet done so */
- FreeConsole();
-
- if (name)
- {
- DWORD tid;
- HANDLE hThread;
- /* NOTE: this is static so the module can continue to
- * access these args while we go on to other things
- */
- static tty_info tty;
- tty.instance = GetModuleHandle(NULL);
- tty.phandler = phandler;
- tty.parent = NULL;
- tty.name = name;
- tty.type = 2;
- RegisterWindows9xService(TRUE);
- hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
- (LPVOID)&tty, 0, &tid);
- if (hThread)
- {
- CloseHandle(hThread);
- return TRUE;
- }
- }
- else /* remove */
- {
- if (monitor_hwnd)
- SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
- RegisterWindows9xService(FALSE);
- return TRUE;
- }
- return FALSE;
-}
-
-
-/* Exported function that registers a HandlerRoutine to accept missing
- * Win9x CTRL_EVENTs from the tty window, as NT does without a hassle.
- * If add is 1 or 2, register the handler, if 2 also mark it as a service.
- * If add is 0 deregister the handler, and unmark if a service
- */
-BOOL __declspec(dllexport) WINAPI FixConsoleCtrlHandler(
- PHANDLER_ROUTINE phandler,
- INT add)
-{
- HWND parent;
-
- if (add)
- {
- HANDLE hThread;
- DWORD tid;
- /* NOTE: this is static so the module can continue to
- * access these args while we go on to other things
- */
- static tty_info tty;
- EnumWindows(EnumttyWindow, (LPARAM)&parent);
- if (!parent) {
-#ifdef DBG
- DbgPrintf("A EnumttyWindow failed (%d)\r\n", GetLastError());
-#endif
- return FALSE;
- }
- tty.instance = GetModuleHandle(NULL);
- tty.phandler = phandler;
- tty.parent = parent;
- tty.type = add;
- if (add == 2) {
- tty.name = "ttyService";
- RegisterWindows9xService(TRUE);
- }
- else
- tty.name = "ttyMonitor";
- hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
- (LPVOID)&tty, 0, &tid);
- if (!hThread)
- return FALSE;
- CloseHandle(hThread);
- hmodHook = LoadLibrary("Win9xConHook.dll");
- if (hmodHook)
- {
- hhkGetMessage = SetWindowsHookEx(WH_GETMESSAGE,
- (HOOKPROC)GetProcAddress(hmodHook, "GetMsgProc"), hmodHook, 0);
- //hhkCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC,
- // (HOOKPROC)GetProcAddress(hmodHook, "CallWndProc"), hmodHook, 0);
- }
- return TRUE;
- }
- else /* remove */
- {
- if (monitor_hwnd) {
- SendMessage(monitor_hwnd, WM_DESTROY, 0, 0);
- }
- if (hmodHook)
- {
- if (hhkGetMessage) {
- UnhookWindowsHookEx(hhkGetMessage);
- hhkGetMessage = NULL;
- }
- //if (hhkCallWndProc) {
- // UnhookWindowsHookEx(hhkCallWndProc);
- // hhkCallWndProc = NULL;
- //}
- FreeLibrary(hmodHook);
- hmodHook = NULL;
- }
- if (is_service)
- RegisterWindows9xService(FALSE);
- return TRUE;
- }
- return FALSE;
-}
-
-
-/* The following internal helpers are only used within the app's context
- */
-
-/* ttyConsoleCreateThread is the process that runs within the user app's
- * context. It creates and pumps the messages of a hidden monitor window,
- * watching for messages from the system, or the associated subclassed tty
- * window. Things can happen in our context that can't be done from the
- * tty's context, and visa versa, so the subclass procedure and this hidden
- * window work together to make it all happen.
- */
-static DWORD WINAPI ttyConsoleCtrlThread(LPVOID tty)
-{
- WNDCLASS wc;
- MSG msg;
- wc.style = CS_GLOBALCLASS;
- wc.lpfnWndProc = ttyConsoleCtrlWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 8;
- wc.hInstance = NULL;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- if (((tty_info*)tty)->parent)
- wc.lpszClassName = "ttyConHookChild";
- else
- wc.lpszClassName = "ApacheWin95ServiceMonitor";
-
- if (!RegisterClass(&wc)) {
-#ifdef DBG
- DbgPrintf("A proc %8.8x Error creating class %s (%d)\r\n",
- GetCurrentProcessId(), wc.lpszClassName, GetLastError());
-#endif
- return 0;
- }
-
- /* Create an invisible window */
- monitor_hwnd = CreateWindow(wc.lpszClassName, ((tty_info*)tty)->name,
- WS_OVERLAPPED & ~WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL,
- ((tty_info*)tty)->instance, tty);
-
- if (!monitor_hwnd) {
-#ifdef DBG
- DbgPrintf("A proc %8.8x Error creating window %s %s (%d)\r\n",
- GetCurrentProcessId(), wc.lpszClassName,
- ((tty_info*)tty)->name, GetLastError());
-#endif
- return 0;
- }
-
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- /* Tag again as deleted, just in case we missed WM_DESTROY */
- monitor_hwnd = NULL;
- return 0;
-}
-
-
-/* This is the WndProc procedure for our invisible window.
- * When our subclasssed tty window receives the WM_CLOSE, WM_ENDSESSION,
- * or WM_QUERYENDSESSION messages, the message is dispatched to our hidden
- * window (this message process), and we call the installed HandlerRoutine
- * that was registered by the app.
- */
-static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
-{
- if (msg == WM_CREATE)
- {
- tty_info *tty = (tty_info*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
- SetWindowLong(hwnd, gwltty_phandler, (LONG)tty->phandler);
- SetWindowLong(hwnd, gwltty_ttywnd, (LONG)tty->parent);
-#ifdef DBG
- DbgPrintf("A proc %8.8x created %8.8x %s for tty wnd %8.8x\r\n",
- GetCurrentProcessId(), hwnd,
- tty->name, tty->parent);
-#endif
- if (tty->parent) {
- SetProp(tty->parent, hookwndprop, hwnd);
- PostMessage(tty->parent, hookwndmsg,
- tty->type, (LPARAM)tty->parent);
- }
- return 0;
- }
- else if (msg == WM_DESTROY)
- {
- HWND parent = (HWND)GetWindowLong(hwnd, gwltty_ttywnd);
-#ifdef DBG
- DbgPrintf("A proc %8.8x destroyed %8.8x ttyConHookChild\r\n",
- GetCurrentProcessId(), hwnd);
-#endif
- if (parent) {
- RemoveProp(parent, hookwndprop);
- SendMessage(parent, hookwndmsg, 0, (LPARAM)parent);
- }
- monitor_hwnd = NULL;
- }
- else if (msg == WM_CLOSE)
- {
- PHANDLER_ROUTINE phandler =
- (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
- LRESULT rv = phandler(CTRL_CLOSE_EVENT);
-#ifdef DBG
- DbgPrintf("A proc %8.8x invoked CTRL_CLOSE_EVENT "
- "returning %d\r\n",
- GetCurrentProcessId(), rv);
-#endif
- if (rv)
- return !rv;
- }
- else if ((msg == WM_QUERYENDSESSION) || (msg == WM_ENDSESSION))
- {
- if (lParam & ENDSESSION_LOGOFF)
- {
- PHANDLER_ROUTINE phandler =
- (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
- LRESULT rv = phandler(CTRL_LOGOFF_EVENT);
-#ifdef DBG
- DbgPrintf("A proc %8.8x invoked CTRL_LOGOFF_EVENT "
- "returning %d\r\n",
- GetCurrentProcessId(), rv);
-#endif
- if (rv)
- return ((msg == WM_QUERYENDSESSION) ? rv : !rv);
- }
- else
- {
- PHANDLER_ROUTINE phandler =
- (PHANDLER_ROUTINE)GetWindowLong(hwnd, gwltty_phandler);
- LRESULT rv = phandler(CTRL_SHUTDOWN_EVENT);
-#ifdef DBG
- DbgPrintf("A proc %8.8x invoked CTRL_SHUTDOWN_EVENT "
- "returning %d\r\n", GetCurrentProcessId(), rv);
-#endif
- if (rv)
- return ((msg == WM_QUERYENDSESSION) ? rv : !rv);
- }
- }
- return (DefWindowProc(hwnd, msg, wParam, lParam));
-}
-
-
-/* The following internal helpers are invoked by the hooked tty and our app
- */
-
-
-/* Register or deregister the current process as a Windows9x style service.
- * Experience shows this call is ignored across processes, so the second
- * arg to RegisterServiceProcess (process group id) is effectively useless.
- */
-static LRESULT WINAPI RegisterWindows9xService(BOOL set_service)
-{
- static HINSTANCE hkernel;
- static DWORD (WINAPI *register_service_process)(DWORD, DWORD) = NULL;
- BOOL rv;
-
- if (set_service == is_service)
- return 1;
-
-#ifdef DBG
- DbgPrintf("R %s proc %8.8x as a service\r\n",
- set_service ? "installing" : "removing",
- GetCurrentProcessId());
-#endif
-
- if (!register_service_process)
- {
- /* Obtain a handle to the kernel library */
- hkernel = LoadLibrary("KERNEL32.DLL");
- if (!hkernel)
- return 0;
-
- /* Find the RegisterServiceProcess function */
- register_service_process = (DWORD (WINAPI *)(DWORD, DWORD))
- GetProcAddress(hkernel, "RegisterServiceProcess");
- if (register_service_process == NULL) {
- FreeLibrary(hkernel);
- return 0;
- }
- }
-
- /* Register this process as a service */
- rv = register_service_process(0, set_service != FALSE);
- if (rv)
- is_service = set_service;
-
- if (!is_service)
- {
- /* Unload the kernel library */
- FreeLibrary(hkernel);
- register_service_process = NULL;
- }
- return rv;
-}
-
-
-/*
- * This function only works when this process is the active process
- * (e.g. once it is running a child process, it can no longer determine
- * which console window is its own.)
- */
-static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd)
-{
- char tmp[8];
- if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, "tty"))
- {
- DWORD wndproc, thisproc = GetCurrentProcessId();
- GetWindowThreadProcessId(wnd, &wndproc);
- if (wndproc == thisproc) {
- *((HWND*)retwnd) = wnd;
- return FALSE;
- }
- }
- return TRUE;
-}
-
-
-/* The remaining code all executes --in the tty's own process context--
- *
- * That means special attention must be paid to what it's doing...
- */
-
-/* Subclass message process for the tty window
- *
- * This code -handles- WM_CLOSE, WM_ENDSESSION and WM_QUERYENDSESSION
- * by dispatching them to the window identified by the hookwndprop
- * property atom set against our window. Messages are then dispatched
- * to origwndprop property atom we set against the window when we
- * injected this subclass. This trick did not work with simply a hook.
- */
-static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
-{
- WNDPROC origproc = (WNDPROC) GetProp(hwnd, origwndprop);
- if (!origproc)
- return 0;
-
- if (msg == WM_NCDESTROY
- || (msg == hookwndmsg && !LOWORD(wParam) && (HWND)lParam == hwnd))
- {
- if (is_subclassed) {
-#ifdef DBG
- DbgPrintf("W proc %08x hwnd:%08x Subclass removed\r\n",
- GetCurrentProcessId(), hwnd);
-#endif
- if (is_service)
- RegisterWindows9xService(FALSE);
- SetWindowLong(hwnd, GWL_WNDPROC, (LONG)origproc);
- RemoveProp(hwnd, origwndprop);
- RemoveProp(hwnd, hookwndprop);
- is_subclassed = FALSE;
- //if (hmodLock)
- // FreeLibrary(hmodLock);
- //hmodLock = NULL;
- }
- }
- else if (msg == WM_CLOSE || msg == WM_ENDSESSION
- || msg == WM_QUERYENDSESSION)
- {
- HWND child = (HWND)GetProp(hwnd, hookwndprop);
- if (child) {
-#ifdef DBG
- DbgPrintf("W proc %08x hwnd:%08x forwarded msg:%d\r\n",
- GetCurrentProcessId(), hwnd, msg);
-#endif
- return SendMessage(child, msg, wParam, lParam);
- }
- }
- return CallWindowProc(origproc, hwnd, msg, wParam, lParam);
-}
-
-
-/* HookProc, once installed, is responsible for subclassing the system
- * tty windows. It generally does nothing special itself, since
- * research indicates that it cannot deal well with the messages we are
- * interested in, that is, WM_CLOSE, WM_QUERYSHUTDOWN and WM_SHUTDOWN
- * of the tty process.
- *
- * Respond and subclass only when a WM_NULL is received by the window.
- */
-int HookProc(int hc, HWND *hwnd, UINT *msg, WPARAM *wParam, LPARAM *lParam)
-{
- if (is_tty == -1 && *hwnd)
- {
- char ttybuf[8];
- HWND htty;
- hwtty = *hwnd;
- while (htty = GetParent(hwtty))
- hwtty = htty;
- is_tty = (GetClassName(hwtty, ttybuf, sizeof(ttybuf))
- && !strcmp(ttybuf, "tty"));
-#ifdef DBG
- if (is_tty)
- DbgPrintf("H proc %08x tracking hwnd %08x\r\n",
- GetCurrentProcessId(), hwtty);
-#endif
- }
-
- if (*msg == hookwndmsg && *wParam && *lParam == (LPARAM)hwtty && is_tty)
- {
- WNDPROC origproc = (WNDPROC)GetWindowLong(hwtty, GWL_WNDPROC);
- //char myname[MAX_PATH];
- //if (GetModuleFileName(hmodThis, myname, sizeof(myname)))
- // hmodLock = LoadLibrary(myname);
- SetProp(hwtty, origwndprop, origproc);
- SetWindowLong(hwtty, GWL_WNDPROC, (LONG)WndProc);
- is_subclassed = TRUE;
-#ifdef DBG
- DbgPrintf("H proc %08x hwnd:%08x Subclassed\r\n",
- GetCurrentProcessId(), hwtty);
-#endif
- if (LOWORD(*wParam) == 2)
- RegisterWindows9xService(TRUE);
- }
-
- return -1;
-}
-
-
-/*
- * PostMessage Hook:
- */
-LRESULT __declspec(dllexport) CALLBACK GetMsgProc(INT hc, WPARAM wParam,
- LPARAM lParam)
-{
- PMSG pmsg;
-
- pmsg = (PMSG)lParam;
-
- if (pmsg) {
- int rv = HookProc(hc, &pmsg->hwnd, &pmsg->message,
- &pmsg->wParam, &pmsg->lParam);
- if (rv != -1)
- return rv;
- }
- /*
- * CallNextHookEx apparently ignores the hhook argument, so pass NULL
- */
- return CallNextHookEx(NULL, hc, wParam, lParam);
-}
-
-
-/*
- * SendMessage Hook:
- */
-LRESULT __declspec(dllexport) CALLBACK CallWndProc(INT hc, WPARAM wParam,
- LPARAM lParam)
-{
- PCWPSTRUCT pcwps = (PCWPSTRUCT)lParam;
-
- if (pcwps) {
- int rv = HookProc(hc, &pcwps->hwnd, &pcwps->message,
- &pcwps->wParam, &pcwps->lParam);
- if (rv != -1)
- return rv;
- }
- /*
- * CallNextHookEx apparently ignores the hhook argument, so pass NULL
- */
- return CallNextHookEx(NULL, hc, wParam, lParam);
-}
-
-
-#ifdef DBG
-VOID DbgPrintf(
- LPTSTR fmt,
- ...
- )
-{
- static HANDLE mutex;
- va_list marker;
- TCHAR szBuf[256];
- DWORD t;
- HANDLE gDbgOut;
-
- va_start(marker, fmt);
- wvsprintf(szBuf, fmt, marker);
- va_end(marker);
-
- if (!mutex)
- mutex = CreateMutex(NULL, FALSE, "Win9xConHookDbgOut");
- WaitForSingleObject(mutex, INFINITE);
- gDbgOut = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0,
- NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
- WriteFile(gDbgOut, szBuf, strlen(szBuf), &t, NULL);
- CloseHandle(gDbgOut);
- ReleaseMutex(mutex);
-}
-#endif
-
-#endif /* WIN32 */
diff --git a/server/mpm/winnt/Win9xConHook.def b/server/mpm/winnt/Win9xConHook.def
deleted file mode 100644
index 85ec166404..0000000000
--- a/server/mpm/winnt/Win9xConHook.def
+++ /dev/null
@@ -1,10 +0,0 @@
-LIBRARY Win9xConHook
-
-EXETYPE WINDOWS
-
-EXPORTS
- DllMain
- GetMsgProc
- CallWndProc
- FixConsoleCtrlHandler
- Windows9xServiceCtrlHandler
diff --git a/server/mpm/winnt/Win9xConHook.dsp b/server/mpm/winnt/Win9xConHook.dsp
deleted file mode 100644
index 56ad1180a9..0000000000
--- a/server/mpm/winnt/Win9xConHook.dsp
+++ /dev/null
@@ -1,103 +0,0 @@
-# Microsoft Developer Studio Project File - Name="Win9xConHook" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=Win9xConHook - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "Win9xConHook.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "Win9xConHook.mak" CFG="Win9xConHook - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "Win9xConHook - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "Win9xConHook - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "Win9xConHook - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir ".\Release"
-# PROP BASE Intermediate_Dir ".\Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Release\Win9xConHook" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /machine:I386 /base:"0x1c0f0000"
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /machine:I386 /base:"0x1c0f0000"
-
-!ELSEIF "$(CFG)" == "Win9xConHook - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fd"Debug\Win9xConHook" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /base:"0x1c0f0000"
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /base:"0x1c0f0000"
-
-!ENDIF
-
-# Begin Target
-
-# Name "Win9xConHook - Win32 Release"
-# Name "Win9xConHook - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\Win9xConHook.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\Win9xConHook.def
-# End Source File
-# Begin Source File
-
-SOURCE=.\Win9xConHook.h
-# End Source File
-# End Target
-# End Project
diff --git a/server/mpm/winnt/Win9xConHook.h b/server/mpm/winnt/Win9xConHook.h
deleted file mode 100644
index 312e82cd2d..0000000000
--- a/server/mpm/winnt/Win9xConHook.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef AP_WIN9XCONHOOK_H
-#define AP_WIN9XCONHOOK_H
-
-#ifdef WIN32
-
-/* Windows9xServiceCtrlHandler registers a handler routine, frees the
- * console window, and registers this process as a service in Win9x.
- * It creats a hidden window of class "ApacheWin95ServiceMonitor"
- * and titled by the name passed, which passes the WM_SHUTDOWN message
- * through the given HandlerRoutine's CTRL_SHUTDOWN event.
- * Call with name of NULL to remove the Service handler.
- */
-BOOL WINAPI Windows9xServiceCtrlHandler(PHANDLER_ROUTINE phandler, LPCSTR name);
-
-
-/* FixConsoleControlHandler registers a handler routine with the
- * Win9xConHook.dll, creating a hidden window and forwarding the
- * WM_ENDSESSION and WM_CLOSE messages to the given HandlerRoutine
- * as CTRL_SHUTDOWN_EVENT, CTRL_LOGOFF_EVENT and CTRL_CLOSE_EVENT.
- * The application should still use SetConsoleCtrlHandler to grab
- * the CTRL_BREAK_EVENT and CTRL_C_EVENT, if desired.
- */
-BOOL WINAPI FixConsoleCtrlHandler(PHANDLER_ROUTINE phandler, BOOL add);
-
-
-/*
- * Exported PostMessage Hook, never use this directly:
- *
- * LRESULT CALLBACK GetMsgProc(INT hc, WPARAM wParam, LPARAM lParam);
- */
-
-
-/*
- * Exported SendMessage Hook, never use this directly:
- *
- * LRESULT CALLBACK CallWndProc(INT hc, WPARAM wParam, LPARAM lParam);
- */
-
-#endif /* WIN32 */
-
-#endif AP_WIN9XCONHOOK_H \ No newline at end of file
diff --git a/server/mpm/winnt/mpm.h b/server/mpm/winnt/mpm.h
deleted file mode 100644
index 4c17b8a55f..0000000000
--- a/server/mpm/winnt/mpm.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_H
-#define APACHE_MPM_H
-
-/* mpm.h is the place to make declarations that are MPM specific but that must be
- * shared with non-mpm specific code in the server. Hummm, perhaps we can
- * move most of this stuff to mpm_common.h?
- */
-
-#define MPM_NAME "WinNT"
-
-extern int ap_threads_per_child;
-
-#endif /* APACHE_MPM_H */
diff --git a/server/mpm/winnt/mpm_default.h b/server/mpm/winnt/mpm_default.h
deleted file mode 100644
index 876503a47d..0000000000
--- a/server/mpm/winnt/mpm_default.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_DEFAULT_H
-#define APACHE_MPM_DEFAULT_H
-
-/* AP_CHILD_THREAD_FROM_ID is used by the scoreboard. */
-#define AP_CHILD_THREAD_FROM_ID(i) 0, i
-
-/* Number of threads to spawn off by default --- also, if fewer than
- * this free when the caretaker checks, it will spawn more.
- */
-#ifndef DEFAULT_START_THREAD
-#define DEFAULT_START_THREAD 5
-#endif
-
-/* Maximum number of *free* server threads --- more than this, and
- * they will die off.
-#ifndef DEFAULT_MAX_SPARE_THREAD
-#define DEFAULT_MAX_SPARE_THREAD 10
-#endif
-*/
-
-/* Minimum --- fewer than this, and more will be created */
-/*
-#ifndef DEFAULT_MIN_SPARE_THREAD
-#define DEFAULT_MIN_SPARE_THREAD 5
-#endif
-*/
-
-/* Limit on the threads per process. Clients will be locked out if more than
- * this * HARD_SERVER_LIMIT are needed.
- *
- * We keep this for one reason it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#ifndef HARD_THREAD_LIMIT
-#define HARD_THREAD_LIMIT 4096
-#endif
-
-/* Number of servers to spawn off by default
- */
-#ifndef DEFAULT_NUM_DAEMON
-#define DEFAULT_NUM_DAEMON 1
-#endif
-
-/* Limit on the total --- clients will be locked out if more servers than
- * this are needed. It is intended solely to keep the server from crashing
- * when things get out of hand.
- *
- * We keep a hard maximum number of servers, for two reasons --- first off,
- * in case something goes seriously wrong, we want to stop the fork bomb
- * short of actually crashing the machine we're running on by filling some
- * kernel table. Secondly, it keeps the size of the scoreboard file small
- * enough that we can read the whole thing without worrying too much about
- * the overhead.
- */
-#define HARD_SERVER_LIMIT 1
-
-/* Where the main/parent process's pid is logged */
-#ifndef DEFAULT_PIDLOG
-#define DEFAULT_PIDLOG "logs/httpd.pid"
-#endif
-
-/*
- * Interval, in microseconds, between scoreboard maintenance.
- */
-#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-#endif
-
-/* Number of requests to try to handle in a single process. If <= 0,
- * the children don't die off.
- */
-#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-#endif
-
-#endif /* AP_MPM_DEFAULT_H */
diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c
deleted file mode 100644
index 921e362ddd..0000000000
--- a/server/mpm/winnt/mpm_winnt.c
+++ /dev/null
@@ -1,2114 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#define CORE_PRIVATE
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_config.h" /* for read_config */
-#include "http_core.h" /* for get_remote_host */
-#include "http_connection.h"
-#include "apr_portable.h"
-#include "apr_getopt.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-#include "ap_mpm.h"
-#include "ap_config.h"
-#include "ap_listen.h"
-#include "mpm_default.h"
-#include "mpm_winnt.h"
-#include "mpm_common.h"
-#include "scoreboard.h"
-
-
-typedef HANDLE thread;
-#ifdef CONTAINING_RECORD
-#undef CONTAINING_RECORD
-#endif
-#define CONTAINING_RECORD(address, type, field) ((type *)( \
- (PCHAR)(address) - \
- (PCHAR)(&((type *)0)->field)))
-#define PADDED_ADDR_SIZE sizeof(SOCKADDR_IN)+16
-
-typedef struct CompContext {
- struct CompContext *next;
- OVERLAPPED Overlapped;
- apr_socket_t *sock;
- SOCKET accept_socket;
- char buff[2*PADDED_ADDR_SIZE];
- struct sockaddr *sa_server;
- int sa_server_len;
- struct sockaddr *sa_client;
- int sa_client_len;
- apr_pool_t *ptrans;
-} COMP_CONTEXT, *PCOMP_CONTEXT;
-
-typedef enum {
- IOCP_CONNECTION_ACCEPTED = 1,
- IOCP_WAIT_FOR_RECEIVE = 2,
- IOCP_WAIT_FOR_TRANSMITFILE = 3,
- IOCP_SHUTDOWN = 4
-} io_state_e;
-
-/* Queue for managing the passing of COMP_CONTEXTs from
- * the accept thread to the worker threads and back again
- */
-apr_lock_t *qlock;
-COMP_CONTEXT *qhead = NULL;
-COMP_CONTEXT *qtail = NULL;
-
-static HANDLE ThreadDispatchIOCP = NULL;
-
-/* Definitions of WINNT MPM specific config globals */
-static server_rec *server_conf;
-static apr_pool_t *pconf;
-static apr_pool_t *pchild = NULL;
-static int workers_may_exit = 0;
-static int shutdown_in_progress = 0;
-static unsigned int g_blocked_threads = 0;
-static int ap_max_requests_per_child=0;
-
-static char *ap_pid_fname = NULL;
-
-static HANDLE shutdown_event; /* used to signal the parent to shutdown */
-static HANDLE restart_event; /* used to signal the parent to restart */
-static HANDLE exit_event; /* used by parent to signal the child to exit */
-static HANDLE maintenance_event;
-
-static char ap_coredump_dir[MAX_STRING_LEN];
-
-static int one_process = 0;
-static char const* signal_arg;
-
-OSVERSIONINFO osver; /* VER_PLATFORM_WIN32_NT */
-
-apr_lock_t *start_mutex;
-static DWORD my_pid;
-static DWORD parent_pid;
-
-int ap_threads_per_child = 0;
-int ap_daemons_to_start=0;
-
-/* ap_get_max_daemons and ap_my_generation are used by the scoreboard
- * code
- */
-ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */
-
-/* This is the helper code to resolve late bound entry points
- * missing from one or more releases of the Win32 API...
- * but it sure would be nice if we didn't duplicate this code
- * from the APR ;-)
- */
-static const char* const lateDllName[DLL_defined] = {
- "kernel32", "advapi32", "mswsock", "ws2_32" };
-static HMODULE lateDllHandle[DLL_defined] = {
- NULL, NULL, NULL, NULL };
-
-FARPROC ap_load_dll_func(ap_dlltoken_e fnLib, char* fnName, int ordinal)
-{
- if (!lateDllHandle[fnLib]) {
- lateDllHandle[fnLib] = LoadLibrary(lateDllName[fnLib]);
- if (!lateDllHandle[fnLib])
- return NULL;
- }
- if (ordinal)
- return GetProcAddress(lateDllHandle[fnLib], (char *) ordinal);
- else
- return GetProcAddress(lateDllHandle[fnLib], fnName);
-}
-
-/* To share the semaphores with other processes, we need a NULL ACL
- * Code from MS KB Q106387
- */
-static PSECURITY_ATTRIBUTES GetNullACL()
-{
- PSECURITY_DESCRIPTOR pSD;
- PSECURITY_ATTRIBUTES sa;
-
- sa = (PSECURITY_ATTRIBUTES) LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
- pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
- SECURITY_DESCRIPTOR_MIN_LENGTH);
- if (pSD == NULL || sa == NULL) {
- return NULL;
- }
- apr_set_os_error(0);
- if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)
- || apr_get_os_error()) {
- LocalFree( pSD );
- LocalFree( sa );
- return NULL;
- }
- if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE)
- || apr_get_os_error()) {
- LocalFree( pSD );
- LocalFree( sa );
- return NULL;
- }
- sa->nLength = sizeof(sa);
- sa->lpSecurityDescriptor = pSD;
- sa->bInheritHandle = TRUE;
- return sa;
-}
-
-static void CleanNullACL( void *sa ) {
- if( sa ) {
- LocalFree( ((PSECURITY_ATTRIBUTES)sa)->lpSecurityDescriptor);
- LocalFree( sa );
- }
-}
-
-/*
- * The Win32 call WaitForMultipleObjects will only allow you to wait for
- * a maximum of MAXIMUM_WAIT_OBJECTS (current 64). Since the threading
- * model in the multithreaded version of apache wants to use this call,
- * we are restricted to a maximum of 64 threads. This is a simplistic
- * routine that will increase this size.
- */
-static DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles,
- DWORD dwSeconds)
-{
- time_t tStopTime;
- DWORD dwRet = WAIT_TIMEOUT;
- DWORD dwIndex=0;
- BOOL bFirst = TRUE;
-
- tStopTime = time(NULL) + dwSeconds;
-
- do {
- if (!bFirst)
- Sleep(1000);
- else
- bFirst = FALSE;
-
- for (dwIndex = 0; dwIndex * MAXIMUM_WAIT_OBJECTS < nCount; dwIndex++) {
- dwRet = WaitForMultipleObjects(
- min(MAXIMUM_WAIT_OBJECTS, nCount - (dwIndex * MAXIMUM_WAIT_OBJECTS)),
- lpHandles + (dwIndex * MAXIMUM_WAIT_OBJECTS),
- 0, 0);
-
- if (dwRet != WAIT_TIMEOUT) {
- break;
- }
- }
- } while((time(NULL) < tStopTime) && (dwRet == WAIT_TIMEOUT));
-
- return dwRet;
-}
-
-/*
- * Signalling Apache on NT.
- *
- * Under Unix, Apache can be told to shutdown or restart by sending various
- * signals (HUP, USR, TERM). On NT we don't have easy access to signals, so
- * we use "events" instead. The parent apache process goes into a loop
- * where it waits forever for a set of events. Two of those events are
- * called
- *
- * apPID_shutdown
- * apPID_restart
- *
- * (where PID is the PID of the apache parent process). When one of these
- * is signalled, the Apache parent performs the appropriate action. The events
- * can become signalled through internal Apache methods (e.g. if the child
- * finds a fatal error and needs to kill its parent), via the service
- * control manager (the control thread will signal the shutdown event when
- * requested to stop the Apache service), from the -k Apache command line,
- * or from any external program which finds the Apache PID from the
- * httpd.pid file.
- *
- * The signal_parent() function, below, is used to signal one of these events.
- * It can be called by any child or parent process, since it does not
- * rely on global variables.
- *
- * On entry, type gives the event to signal. 0 means shutdown, 1 means
- * graceful restart.
- */
-/*
- * Initialise the signal names, in the global variables signal_name_prefix,
- * signal_restart_name and signal_shutdown_name.
- */
-#define MAX_SIGNAL_NAME 30 /* Long enough for apPID_shutdown, where PID is an int */
-char signal_name_prefix[MAX_SIGNAL_NAME];
-char signal_restart_name[MAX_SIGNAL_NAME];
-char signal_shutdown_name[MAX_SIGNAL_NAME];
-void setup_signal_names(char *prefix)
-{
- apr_snprintf(signal_name_prefix, sizeof(signal_name_prefix), prefix);
- apr_snprintf(signal_shutdown_name, sizeof(signal_shutdown_name),
- "%s_shutdown", signal_name_prefix);
- apr_snprintf(signal_restart_name, sizeof(signal_restart_name),
- "%s_restart", signal_name_prefix);
-}
-
-void signal_parent(int type)
-{
- HANDLE e;
- char *signal_name;
-
- /* after updating the shutdown_pending or restart flags, we need
- * to wake up the parent process so it can see the changes. The
- * parent will normally be waiting for either a child process
- * to die, or for a signal on the "spache-signal" event. So set the
- * "apache-signal" event here.
- */
- if (one_process) {
- return;
- }
-
- switch(type) {
- case 0: signal_name = signal_shutdown_name; break;
- case 1: signal_name = signal_restart_name; break;
- default: return;
- }
- e = OpenEvent(EVENT_ALL_ACCESS, FALSE, signal_name);
- if (!e) {
- /* Um, problem, can't signal the parent, which means we can't
- * signal ourselves to die. Ignore for now...
- */
- ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), server_conf,
- "OpenEvent on %s event", signal_name);
- return;
- }
- if (SetEvent(e) == 0) {
- /* Same problem as above */
- ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), server_conf,
- "SetEvent on %s event", signal_name);
- CloseHandle(e);
- return;
- }
- CloseHandle(e);
-}
-
-static int volatile is_graceful = 0;
-
-AP_DECLARE(int) ap_graceful_stop_signalled(void)
-{
- return is_graceful;
-}
-
-AP_DECLARE(void) ap_start_shutdown(void)
-{
- signal_parent(0);
-}
-
-AP_DECLARE(void) ap_start_restart(int gracefully)
-{
- is_graceful = gracefully;
- signal_parent(1);
-}
-
-
-/*
- * find_ready_listener()
- * Only used by Win9* and should go away when the win9*_accept() function is
- * reimplemented using apr_poll().
- */
-static ap_listen_rec *head_listener;
-static APR_INLINE ap_listen_rec *find_ready_listener(fd_set * main_fds)
-{
- ap_listen_rec *lr;
- SOCKET nsd;
-
- for (lr = head_listener; lr ; lr = lr->next) {
- apr_os_sock_get(&nsd, lr->sd);
- if (FD_ISSET(nsd, main_fds)) {
- head_listener = lr->next;
- if (head_listener == NULL)
- head_listener = ap_listeners;
-
- return (lr);
- }
- }
- return NULL;
-}
-
-/*
- * get_listeners_from_parent()
- * The listen sockets are opened in the parent. This function, which runs
- * exclusively in the child process, receives them from the parent and
- * makes them availeble in the child.
- */
-static int get_listeners_from_parent(server_rec *s)
-{
- WSAPROTOCOL_INFO WSAProtocolInfo;
- HANDLE pipe;
- ap_listen_rec *lr;
- DWORD BytesRead;
- int num_listeners = 0;
- SOCKET nsd;
-
- /* Set up a default listener if necessary */
- if (ap_listeners == NULL) {
- ap_listen_rec *lr;
- lr = apr_palloc(s->process->pool, sizeof(ap_listen_rec));
- if (!lr)
- return 0;
- lr->sd = NULL;
- lr->next = ap_listeners;
- ap_listeners = lr;
- }
-
- /* Open the pipe to the parent process to receive the inherited socket
- * data. The sockets have been set to listening in the parent process.
- */
- pipe = GetStdHandle(STD_INPUT_HANDLE);
- for (lr = ap_listeners; lr; lr = lr->next) {
- if (!ReadFile(pipe, &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO),
- &BytesRead, (LPOVERLAPPED) NULL)) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "setup_inherited_listeners: Unable to read socket data from parent");
- signal_parent(0); /* tell parent to die */
- exit(1);
- }
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: setup_inherited_listener() read = %d bytes of WSAProtocolInfo.", my_pid);
- nsd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
- &WSAProtocolInfo, 0, 0);
- if (nsd == INVALID_SOCKET) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), server_conf,
- "Child %d: setup_inherited_listeners(), WSASocket failed to open the inherited socket.", my_pid);
- signal_parent(0); /* tell parent to die */
- exit(1);
- }
- apr_os_sock_put(&lr->sd, &nsd, pconf);
- num_listeners++;
- }
-
- CloseHandle(pipe);
-
- return num_listeners;
-}
-
-
-/* Windows 9x specific code...
- * Accept processing for on Windows 95/98 uses a producer/consumer queue
- * model. A single thread accepts connections and queues the accepted socket
- * to the accept queue for consumption by a pool of worker threads.
- *
- * win9x_accept()
- * The accept threads runs this function, which accepts connections off
- * the network and calls add_job() to queue jobs to the accept_queue.
- * add_job()/remove_job()
- * Add or remove an accepted socket from the list of sockets
- * connected to clients. allowed_globals.jobmutex protects
- * against multiple concurrent access to the linked list of jobs.
- * win9x_get_connection()
- * Calls remove_job() to pull a job from the accept queue. All the worker
- * threads block on remove_job.
- */
-
-typedef struct joblist_s {
- struct joblist_s *next;
- int sock;
-} joblist;
-
-typedef struct globals_s {
- HANDLE jobsemaphore;
- joblist *jobhead;
- joblist *jobtail;
- apr_lock_t *jobmutex;
- int jobcount;
-} globals;
-
-globals allowed_globals = {NULL, NULL, NULL, NULL, 0};
-#define MAX_SELECT_ERRORS 100
-
-static void add_job(int sock)
-{
- joblist *new_job;
-
- new_job = (joblist *) malloc(sizeof(joblist));
- if (new_job == NULL) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Ouch! Out of memory in add_job()!");
- return;
- }
- new_job->next = NULL;
- new_job->sock = sock;
-
- apr_lock_acquire(allowed_globals.jobmutex);
-
- if (allowed_globals.jobtail != NULL)
- allowed_globals.jobtail->next = new_job;
- allowed_globals.jobtail = new_job;
- if (!allowed_globals.jobhead)
- allowed_globals.jobhead = new_job;
- allowed_globals.jobcount++;
- ReleaseSemaphore(allowed_globals.jobsemaphore, 1, NULL);
-
- apr_lock_release(allowed_globals.jobmutex);
-}
-
-static int remove_job(void)
-{
- joblist *job;
- int sock;
-
- WaitForSingleObject(allowed_globals.jobsemaphore, INFINITE);
- apr_lock_acquire(allowed_globals.jobmutex);
-
- if (shutdown_in_progress && !allowed_globals.jobhead) {
- apr_lock_release(allowed_globals.jobmutex);
- return (-1);
- }
- job = allowed_globals.jobhead;
- ap_assert(job);
- allowed_globals.jobhead = job->next;
- if (allowed_globals.jobhead == NULL)
- allowed_globals.jobtail = NULL;
- apr_lock_release(allowed_globals.jobmutex);
- sock = job->sock;
- free(job);
-
- return (sock);
-}
-
-static void win9x_accept(void * dummy)
-{
- int requests_this_child = 0;
- struct timeval tv;
- fd_set main_fds;
- int wait_time = 1;
- int csd;
- SOCKET nsd = INVALID_SOCKET;
- struct sockaddr_in sa_client;
- int count_select_errors = 0;
- int rc;
- int clen;
- ap_listen_rec *lr;
- struct fd_set listenfds;
- SOCKET listenmaxfd = INVALID_SOCKET;
-
- /* Setup the listeners
- * ToDo: Use apr_poll()
- */
- FD_ZERO(&listenfds);
- for (lr = ap_listeners; lr; lr = lr->next) {
- if (lr->sd != NULL) {
- apr_os_sock_get(&nsd, lr->sd);
- FD_SET(nsd, &listenfds);
- if (listenmaxfd == INVALID_SOCKET || nsd > listenmaxfd) {
- listenmaxfd = nsd;
- }
- }
- }
- head_listener = ap_listeners;
-
- while (!shutdown_in_progress) {
- if (ap_max_requests_per_child && (requests_this_child > ap_max_requests_per_child)) {
- break;
- }
-
- tv.tv_sec = wait_time;
- tv.tv_usec = 0;
- memcpy(&main_fds, &listenfds, sizeof(fd_set));
-
- rc = select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
-
- if (rc == 0 || (rc == SOCKET_ERROR && APR_STATUS_IS_EINTR(apr_get_netos_error()))) {
- count_select_errors = 0; /* reset count of errors */
- continue;
- }
- else if (rc == SOCKET_ERROR) {
- /* A "real" error occurred, log it and increment the count of
- * select errors. This count is used to ensure we don't go into
- * a busy loop of continuous errors.
- */
- ap_log_error(APLOG_MARK, APLOG_INFO, apr_get_netos_error(), server_conf,
- "select failed with error %d", apr_get_netos_error());
- count_select_errors++;
- if (count_select_errors > MAX_SELECT_ERRORS) {
- shutdown_in_progress = 1;
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), server_conf,
- "Too many errors in select loop. Child process exiting.");
- break;
- }
- } else {
- ap_listen_rec *lr;
-
- lr = find_ready_listener(&main_fds);
- if (lr != NULL) {
- /* fetch the native socket descriptor */
- apr_os_sock_get(&nsd, lr->sd);
- }
- }
-
- do {
- clen = sizeof(sa_client);
- csd = accept(nsd, (struct sockaddr *) &sa_client, &clen);
- if (csd == INVALID_SOCKET) {
- csd = -1;
- }
- } while (csd < 0 && APR_STATUS_IS_EINTR(apr_get_netos_error()));
-
- if (csd < 0) {
- if (APR_STATUS_IS_ECONNABORTED(apr_get_netos_error())) {
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), server_conf,
- "accept: (client socket)");
- }
- }
- else {
- add_job(csd);
- requests_this_child++;
- }
- }
- SetEvent(exit_event);
-}
-
-static PCOMP_CONTEXT win9x_get_connection(PCOMP_CONTEXT context)
-{
- int len;
-
- if (context == NULL) {
- /* allocate the completion context and the transaction pool */
- context = apr_pcalloc(pconf, sizeof(COMP_CONTEXT));
- if (!context) {
- ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), server_conf,
- "win9x_get_connection: apr_pcalloc() failed. Process will exit.");
- return NULL;
- }
- apr_pool_create(&context->ptrans, pconf);
- }
-
-
- while (1) {
- apr_pool_clear(context->ptrans);
- context->accept_socket = remove_job();
- if (context->accept_socket == -1) {
- return NULL;
- }
- len = sizeof(struct sockaddr);
- context->sa_server = apr_palloc(context->ptrans, len);
- if (getsockname(context->accept_socket,
- context->sa_server, &len)== SOCKET_ERROR) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), server_conf,
- "getsockname failed");
- continue;
- }
- len = sizeof(struct sockaddr);
- context->sa_client = apr_palloc(context->ptrans, len);
- if ((getpeername(context->accept_socket,
- context->sa_client, &len)) == SOCKET_ERROR) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), server_conf,
- "getpeername failed");
- memset(&context->sa_client, '\0', sizeof(context->sa_client));
- }
-
- /* do we NEED_DUPPED_CSD ?? */
-
- return context;
- }
-}
-/* Windows NT/2000 specific code...
- * Accept processing for on Windows NT uses a producer/consumer queue
- * model. An accept thread accepts connections off the network then issues
- * PostQueuedCompletionStatus() to awake a thread blocked on the ThreadDispatch
- * IOCompletionPort.
- *
- * winnt_accept()
- * One or more accept threads run in this function, each of which accepts
- * connections off the network and calls PostQueuedCompletionStatus() to
- * queue an io completion packet to the ThreadDispatch IOCompletionPort.
- * winnt_get_connection()
- * Worker threads block on the ThreadDispatch IOCompletionPort awaiting
- * connections to service.
- */
-static void winnt_accept(void *listen_socket)
-{
- static int num_completion_contexts = 0;
- static int requests_this_child = 0;
- PCOMP_CONTEXT pCompContext;
- DWORD BytesRead;
- SOCKET nlsd;
- int lasterror;
-
- nlsd = (SOCKET) listen_socket;
-
- while (!shutdown_in_progress) {
- if (ap_max_requests_per_child && (requests_this_child > ap_max_requests_per_child)) {
- break;
- }
- pCompContext = NULL;
- /* Grab a context off the queue */
- apr_lock_acquire(qlock);
- if (qhead) {
- pCompContext = qhead;
- qhead = qhead->next;
- if (!qhead)
- qtail = NULL;
- }
- apr_lock_release(qlock);
-
- /* If we failed to grab a context off the queue, alloc one out of
- * the child pool. There may be up to ap_threads_per_child contexts
- * in the system at once.
- */
- if (!pCompContext) {
- if (num_completion_contexts >= ap_threads_per_child) {
- static int reported = 0;
- if (!reported) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
- "Server ran out of threads to serve requests. Consider "
- "raising the ThreadsPerChild setting");
- reported = 1;
- }
- Sleep(500);
- continue;
- }
- pCompContext = (PCOMP_CONTEXT) apr_pcalloc(pchild, sizeof(COMP_CONTEXT));
-
- pCompContext->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (pCompContext->Overlapped.hEvent == NULL) {
- ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), server_conf,
- "winnt_accept: CreateEvent failed. Process will exit.");
- // return -1;
- }
- pCompContext->accept_socket = INVALID_SOCKET;
- num_completion_contexts++;
- }
-
- again:
- /* Create and initialize the accept socket */
- if (pCompContext->accept_socket == INVALID_SOCKET) {
- pCompContext->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-
- if (pCompContext->accept_socket == INVALID_SOCKET) {
- ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_netos_error(), server_conf,
- "winnt_accept: socket() failed. Process will exit.");
- // return -1;
- }
-
- /* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */
- if (setsockopt(pCompContext->accept_socket, SOL_SOCKET,
- SO_UPDATE_ACCEPT_CONTEXT, (char *)&nlsd,
- sizeof(nlsd))) {
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), server_conf,
- "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed.");
- /* Not a failure condition. Keep running. */
- }
- }
-
- /* AcceptEx on the completion context. The completion context will be
- * signaled when a connection is accepted.
- */
- if (!AcceptEx(nlsd, pCompContext->accept_socket,
- pCompContext->buff,
- 0,
- PADDED_ADDR_SIZE,
- PADDED_ADDR_SIZE,
- &BytesRead,
- &pCompContext->Overlapped)) {
- lasterror = apr_get_netos_error();
- if (lasterror == APR_FROM_OS_ERROR(WSAEINVAL)) {
- /* Hack alert. Occasionally, TransmitFile will not recycle the
- * accept socket (usually when the client disconnects early).
- * Get a new socket and try the call again.
- */
- pCompContext->accept_socket = INVALID_SOCKET;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, lasterror, server_conf,
- "winnt_accept: AcceptEx failed. Reallocate the accept socket and try again.");
- if (shutdown_in_progress)
- break;
- else
- goto again;
- }
- else if (lasterror != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) {
- ap_log_error(APLOG_MARK,APLOG_ERR, lasterror, server_conf,
- "winnt_accept: AcceptEx failed. Process will exit.");
- // return -1;
- }
-
- /* Wait for pending i/o */
- WaitForSingleObject(pCompContext->Overlapped.hEvent, INFINITE);
- }
-
- /* When a connection is received, send an io completion notification to
- * the ThreadDispatchIOCP
- */
- PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_CONNECTION_ACCEPTED,
- &pCompContext->Overlapped);
- requests_this_child++;
- }
-
- if (!shutdown_in_progress) {
- /* Yow, hit an irrecoverable error! Tell the child to die. */
- SetEvent(exit_event);
- }
-}
-static PCOMP_CONTEXT winnt_get_connection(PCOMP_CONTEXT pCompContext)
-{
- int requests_this_child = 0;
- int rc;
- DWORD BytesRead;
- DWORD CompKey;
- LPOVERLAPPED pol;
-
- /* Recycle the completion context.
- * - destroy the ptrans pool
- * - put the context on the queue to be consumed by the accept thread
- * Note: pCompContext->accept_socket may be in a disconnected
- * but reusable state so -don't- close it.
- */
- if (pCompContext) {
- apr_pool_clear(pCompContext->ptrans);
- apr_pool_destroy(pCompContext->ptrans);
- pCompContext->ptrans = NULL;
- pCompContext->next = NULL;
- apr_lock_acquire(qlock);
- if (qtail)
- qtail->next = pCompContext;
- else
- qhead = pCompContext;
- qtail = pCompContext;
- apr_lock_release(qlock);
- }
-
- g_blocked_threads++;
- while (1) {
- if (workers_may_exit) {
- g_blocked_threads--;
- return NULL;
- }
- rc = GetQueuedCompletionStatus(ThreadDispatchIOCP, &BytesRead, &CompKey,
- &pol, INFINITE);
- if (!rc) {
- rc = apr_get_os_error();
- ap_log_error(APLOG_MARK,APLOG_DEBUG, rc, server_conf,
- "Child %d: GetQueuedComplationStatus returned %d", my_pid, rc);
- continue;
- }
-
- switch (CompKey) {
- case IOCP_CONNECTION_ACCEPTED:
- pCompContext = CONTAINING_RECORD(pol, COMP_CONTEXT, Overlapped);
- break;
- case IOCP_SHUTDOWN:
- g_blocked_threads--;
- return NULL;
- default:
- g_blocked_threads--;
- return NULL;
- }
- break;
- }
-
- g_blocked_threads--;
-
- if ((rc = apr_pool_create(&pCompContext->ptrans, NULL)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK,APLOG_DEBUG, rc, server_conf,
- "Child %d: apr_pool_create failed with rc %d", my_pid, rc);
- }
-
- /* Get the local & remote address */
- GetAcceptExSockaddrs(pCompContext->buff,
- 0,
- PADDED_ADDR_SIZE,
- PADDED_ADDR_SIZE,
- &pCompContext->sa_server,
- &pCompContext->sa_server_len,
- &pCompContext->sa_client,
- &pCompContext->sa_client_len);
-
- return pCompContext;
-
-}
-
-/*
- * worker_main()
- * Main entry point for the worker threads. Worker threads block in
- * win*_get_connection() awaiting a connection to service.
- */
-static void worker_main(int thread_num)
-{
- PCOMP_CONTEXT context = NULL;
- apr_os_sock_info_t sockinfo;
-
- while (1) {
- conn_rec *c;
- apr_int32_t disconnected;
-
- ap_update_child_status(0, thread_num, SERVER_READY,
- (request_rec *) NULL);
-
- /* Grab a connection off the network */
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
- context = win9x_get_connection(context);
- }
- else {
- context = winnt_get_connection(context);
- }
-
- if (!context)
- break;
-
- sockinfo.os_sock = &context->accept_socket;
- sockinfo.local = context->sa_server;
- sockinfo.remote = context->sa_client;
- sockinfo.family = APR_INET;
- sockinfo.type = SOCK_STREAM;
- apr_os_sock_make(&context->sock, &sockinfo, context->ptrans);
-
- c = ap_new_connection(context->ptrans, server_conf, context->sock,
- thread_num);
-
- if (c) {
- ap_process_connection(c);
- apr_getsocketopt(context->sock, APR_SO_DISCONNECTED, &disconnected);
- if (!disconnected) {
- context->accept_socket = INVALID_SOCKET;
- ap_lingering_close(c);
- }
- }
- else {
- /* ap_new_connection closes the socket on failure */
- context->accept_socket = INVALID_SOCKET;
- }
- }
-
- ap_update_child_status(0, thread_num, SERVER_DEAD, (request_rec *) NULL);
-
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Thread exiting.", my_pid);
-}
-
-static void cleanup_thread(thread *handles, int *thread_cnt, int thread_to_clean)
-{
- int i;
-
- CloseHandle(handles[thread_to_clean]);
- for (i = thread_to_clean; i < ((*thread_cnt) - 1); i++)
- handles[i] = handles[i + 1];
- (*thread_cnt)--;
-}
-
-/*
- * child_main()
- * Entry point for the main control thread for the child process.
- * This thread creates the accept thread, worker threads and
- * monitors the child process for maintenance and shutdown
- * events.
- */
-static void child_main()
-{
- apr_status_t status;
- HANDLE child_events[2];
- char* exit_event_name;
- int nthreads = ap_threads_per_child;
- int tid;
- thread *child_handles;
- int rv;
- time_t end_time;
- int i;
- int cld;
-
- /* This is the child process or we are running in single process mode. */
- exit_event_name = apr_psprintf(pconf, "apC%d", my_pid);
- setup_signal_names(apr_psprintf(pconf,"ap%d", parent_pid));
-
- if (one_process) {
- /* Single process mode */
- apr_lock_create(&start_mutex, APR_MUTEX, APR_CROSS_PROCESS,
- signal_name_prefix, pconf);
- exit_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name);
- }
- else {
- /* Child process mode */
- apr_lock_child_init(&start_mutex, signal_name_prefix, pconf);
- exit_event = OpenEvent(EVENT_ALL_ACCESS, FALSE, exit_event_name);
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: exit_event_name = %s", my_pid, exit_event_name);
- }
-
- /* Initialize the child_events */
- maintenance_event = CreateEvent(NULL, TRUE, FALSE, NULL);
- child_events[0] = exit_event;
- child_events[1] = maintenance_event;
-
- ap_assert(start_mutex);
- ap_assert(exit_event);
- ap_assert(maintenance_event);
-
- apr_pool_create(&pchild, pconf);
- allowed_globals.jobsemaphore = CreateSemaphore(NULL, 0, 1000000, NULL);
- apr_lock_create(&allowed_globals.jobmutex, APR_MUTEX, APR_INTRAPROCESS, NULL, pchild);
-
- /*
- * Wait until we have permission to start accepting connections.
- * start_mutex is used to ensure that only one child ever
- * goes into the listen/accept loop at once.
- */
- status = apr_lock_acquire(start_mutex);
- if (status != APR_SUCCESS) {
- ap_log_error(APLOG_MARK,APLOG_ERR, status, server_conf,
- "Child %d: Failed to acquire the start_mutex. Process will exit.", my_pid);
- signal_parent(0); /* tell parent to die */
- exit(0);
- }
- ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Acquired the start mutex.", my_pid);
-
- /*
- * Create the worker thread dispatch IOCompletionPort
- * on Windows NT/2000
- */
- if (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {
- /* Create the worker thread dispatch IOCP */
- ThreadDispatchIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
- NULL,
- 0,
- 0); /* CONCURRENT ACTIVE THREADS */
- apr_lock_create(&qlock, APR_MUTEX, APR_INTRAPROCESS, NULL, pchild);
- }
-
- /*
- * Create the pool of worker threads
- */
- ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Starting %d worker threads.", my_pid, nthreads);
- child_handles = (thread) alloca(nthreads * sizeof(int));
- for (i = 0; i < nthreads; i++) {
- ap_update_child_status(0, i, SERVER_STARTING, (request_rec *) NULL);
- child_handles[i] = (thread) _beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE) worker_main,
- (void *) i, 0, &tid);
- }
-
- /*
- * Start the accept thread
- */
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
- _beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE) win9x_accept,
- (void *) i, 0, &tid);
- } else {
- /* Start an accept thread per listener */
- SOCKET nlsd; /* native listening sock descriptor */
- ap_listen_rec *lr;
- for (lr = ap_listeners; lr; lr = lr->next) {
- if (lr->sd != NULL) {
- apr_os_sock_get(&nlsd, lr->sd);
- _beginthreadex(NULL, 1000, (LPTHREAD_START_ROUTINE) winnt_accept,
- (void *) nlsd, 0, &tid);
- }
- }
- }
-
- /* Wait for one of three events:
- * exit_event:
- * The exit_event is signaled by the parent process to notify
- * the child that it is time to exit.
- *
- * maintenance_event:
- * This event is signaled by the worker thread pool to direct
- * this thread to create more completion contexts.
- *
- * TIMEOUT:
- * To do periodic maintenance on the server (check for thread exits,
- * number of completion contexts, etc.)
- */
- while (1) {
- rv = WaitForMultipleObjects(2, (HANDLE *) child_events, FALSE, INFINITE);
- cld = rv - WAIT_OBJECT_0;
- if (rv == WAIT_FAILED) {
- /* Something serious is wrong */
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "Child %d: WAIT_FAILED -- shutting down server");
- break;
- }
- else if (rv == WAIT_TIMEOUT) {
- /* Hey, this cannot happen */
- ap_log_error(APLOG_MARK, APLOG_CRIT, APR_SUCCESS, server_conf,
- "Child %d: WAIT_TIMEOUT -- shutting down server", my_pid);
- break;
- }
- else if (cld == 0) {
- /* Exit event was signaled */
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Exit event signaled. Child process is ending.", my_pid);
- break;
- }
- else {
- /* Child maintenance event signaled */
- ResetEvent(maintenance_event);
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Child maintenance event signaled.", my_pid);
- }
- }
-
- /* Setting is_graceful will cause keep-alive connections to be closed
- * rather than block on the next network read.
- */
- is_graceful = 1;
-
- /* Setting shutdown_in_progress prevents new connections from
- * being accepted but allows the worker threads to continue
- * handling connections that have already been accepted.
- */
- shutdown_in_progress = 1;
-
- /* Close the listening sockets */
- {
- ap_listen_rec *lr;
- for (lr = ap_listeners; lr ; lr = lr->next) {
- apr_socket_close(lr->sd);
- }
- }
-
- /* Give the worker threads time to handle already accepted connections */
- Sleep(1000);
-
- /* Release the start_mutex to let the new process (in the restart
- * scenario) a chance to begin accepting and servicing requests
- */
- ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Releasing the start mutex", my_pid);
- apr_lock_release(start_mutex);
-
- /* Tell the worker threads they may exit when done handling
- * a connection.
- */
- workers_may_exit = 1;
-
- /* Shutdown the worker threads */
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
- for (i = 0; i < nthreads; i++) {
- add_job(-1);
- }
- }
- else { /* Windows NT/2000 */
- /* Post worker threads blocked on the ThreadDispatch IOCompletion port */
- while (g_blocked_threads > 0) {
- ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: %d threads blocked on the completion port", my_pid, g_blocked_threads);
- for (i=g_blocked_threads; i > 0; i--) {
- PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_SHUTDOWN, NULL);
- }
- Sleep(1000);
- }
- /* Empty the accept queue of completion contexts */
- apr_lock_acquire(qlock);
- while (qhead) {
- CloseHandle(qhead->Overlapped.hEvent);
- closesocket(qhead->accept_socket);
- qhead = qhead->next;
- }
- apr_lock_release(qlock);
- }
-
- /* Give busy worker threads a chance to service their connections */
- ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Waiting for %d threads to die.", my_pid, nthreads);
- end_time = time(NULL) + 180;
- while (nthreads) {
- rv = wait_for_many_objects(nthreads, child_handles, end_time - time(NULL));
- if (rv != WAIT_TIMEOUT) {
- rv = rv - WAIT_OBJECT_0;
- ap_assert((rv >= 0) && (rv < nthreads));
- cleanup_thread(child_handles, &nthreads, rv);
- continue;
- }
- break;
- }
-
- /* Kill remaining threads off the hard way */
- for (i = 0; i < nthreads; i++) {
- TerminateThread(child_handles[i], 1);
- CloseHandle(child_handles[i]);
- }
- ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: All worker threads have ended.", my_pid);
-
- CloseHandle(allowed_globals.jobsemaphore);
- apr_lock_destroy(allowed_globals.jobmutex);
- apr_lock_destroy(qlock);
-
- apr_pool_destroy(pchild);
- CloseHandle(exit_event);
-}
-
-static void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *processes)
-{
- int i;
- int handle = 0;
-
- CloseHandle(handles[position]);
- CloseHandle(events[position]);
-
- handle = (int)handles[position];
-
- for (i = position; i < (*processes)-1; i++) {
- handles[i] = handles[i + 1];
- events[i] = events[i + 1];
- }
- (*processes)--;
-}
-
-static int create_process(apr_pool_t *p, HANDLE *handles, HANDLE *events, int *processes)
-{
- int rv;
- char buf[1024];
- char *pCommand;
- char *pEnvVar;
- char *pEnvBlock;
- int i;
- int iEnvBlockLen;
- STARTUPINFO si; /* Filled in prior to call to CreateProcess */
- PROCESS_INFORMATION pi; /* filled in on call to CreateProcess */
-
- ap_listen_rec *lr;
- DWORD BytesWritten;
- HANDLE hPipeRead = NULL;
- HANDLE hPipeWrite = NULL;
- SECURITY_ATTRIBUTES sa = {0};
-
- HANDLE kill_event;
- LPWSAPROTOCOL_INFO lpWSAProtocolInfo;
-
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
-
- /* Build the command line. Should look something like this:
- * C:/apache/bin/apache.exe -f ap_server_confname
- * First, get the path to the executable...
- */
- rv = GetModuleFileName(NULL, buf, sizeof(buf));
- if (rv == sizeof(buf)) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, ERROR_BAD_PATHNAME, server_conf,
- "Parent: Path to Apache process too long");
- return -1;
- } else if (rv == 0) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "Parent: GetModuleFileName() returned NULL for current process.");
- return -1;
- }
-
- /* Build the command line */
- pCommand = apr_psprintf(p, "\"%s\"", buf);
- for (i = 1; i < server_conf->process->argc; i++) {
- pCommand = apr_pstrcat(p, pCommand, " \"", server_conf->process->argv[i], "\"", NULL);
- }
-
- /* Build the environment, since Win9x disrespects the active env */
- pEnvVar = apr_psprintf(p, "AP_PARENT_PID=%i", parent_pid);
- /*
- * Win32's CreateProcess call requires that the environment
- * be passed in an environment block, a null terminated block of
- * null terminated strings.
- */
- i = 0;
- iEnvBlockLen = 1;
- while (_environ[i]) {
- iEnvBlockLen += strlen(_environ[i]) + 1;
- i++;
- }
-
- pEnvBlock = (char *)apr_pcalloc(p, iEnvBlockLen + strlen(pEnvVar) + 1);
- strcpy(pEnvBlock, pEnvVar);
- pEnvVar = strchr(pEnvBlock, '\0') + 1;
-
- i = 0;
- while (_environ[i]) {
- strcpy(pEnvVar, _environ[i]);
- pEnvVar = strchr(pEnvVar, '\0') + 1;
- i++;
- }
- pEnvVar = '\0';
- /* Create a pipe to send socket info to the child */
- if (!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0)) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "Parent: Unable to create pipe to child process.");
- return -1;
- }
-
- /* Give the read end of the pipe (hPipeRead) to the child as stdin. The
- * parent will write the socket data to the child on this pipe.
- */
- memset(&si, 0, sizeof(si));
- memset(&pi, 0, sizeof(pi));
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- si.wShowWindow = SW_HIDE;
- si.hStdInput = hPipeRead;
-
- if (!CreateProcess(NULL, pCommand, NULL, NULL,
- TRUE, /* Inherit handles */
- CREATE_SUSPENDED, /* Creation flags */
- pEnvBlock, /* Environment block */
- NULL,
- &si, &pi)) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "Parent: Not able to create the child process.");
- /*
- * We must close the handles to the new process and its main thread
- * to prevent handle and memory leaks.
- */
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return -1;
- }
-
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Parent: Created child process %d", pi.dwProcessId);
-
- SetEnvironmentVariable("AP_PARENT_PID",NULL);
-
- /* Create the exit_event, apCchild_pid */
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- kill_event = CreateEvent(&sa, TRUE, FALSE, apr_psprintf(pconf,"apC%d", pi.dwProcessId));
- if (!kill_event) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "Parent: Could not create exit event for child process");
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return -1;
- }
-
- /* Assume the child process lives. Update the process and event tables */
- handles[*processes] = pi.hProcess;
- events[*processes] = kill_event;
- (*processes)++;
-
- /* We never store the thread's handle, so close it now. */
- ResumeThread(pi.hThread);
- CloseHandle(pi.hThread);
-
- /* Run the chain of open sockets. For each socket, duplicate it
- * for the target process then send the WSAPROTOCOL_INFO
- * (returned by dup socket) to the child.
- */
- for (lr = ap_listeners; lr; lr = lr->next) {
- int nsd;
- lpWSAProtocolInfo = apr_pcalloc(p, sizeof(WSAPROTOCOL_INFO));
- apr_os_sock_get(&nsd,lr->sd);
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Parent: Duplicating socket %d and sending it to child process %d", nsd, pi.dwProcessId);
- if (WSADuplicateSocket(nsd, pi.dwProcessId,
- lpWSAProtocolInfo) == SOCKET_ERROR) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), server_conf,
- "Parent: WSADuplicateSocket failed for socket %d. Check the FAQ.", lr->sd );
- return -1;
- }
-
- if (!WriteFile(hPipeWrite, lpWSAProtocolInfo, (DWORD) sizeof(WSAPROTOCOL_INFO),
- &BytesWritten,
- (LPOVERLAPPED) NULL)) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "Parent: Unable to write duplicated socket %d to the child.", lr->sd );
- return -1;
- }
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, server_conf,
- "Parent: BytesWritten = %d WSAProtocolInfo = %x20", BytesWritten, *lpWSAProtocolInfo);
- }
-
- CloseHandle(hPipeRead);
- CloseHandle(hPipeWrite);
-
- return 0;
-}
-
-/**********************************************************************
- * master_main()
- * This is the parent process. master_main() creates a multithreaded
- * child process to handle connections, then blocks waiting to receive
- * a shutdown, restart event or child exit event.
- *
- * restart_event
- * - Child is signaled to die gracefully
- * shutdown_event
- * - Child is signaled to die gracefully
- * child_exit_event
- * - Child has died, either normally (max_request_per_child)
- * or abnormally (seg fault, irrecoverable error condition detected by the
- * child)
- **********************************************************************/
-#define MAX_PROCESSES 50 /* must be < MAX_WAIT_OBJECTS-1 */
-static int master_main(server_rec *s, HANDLE shutdown_event, HANDLE restart_event)
-{
- int remaining_children_to_start = ap_daemons_to_start;
- int i;
- int rv, cld;
- int child_num = 0;
- int restart_pending = 0;
- int shutdown_pending = 0;
- int current_live_processes = 0; /* number of child process we know about */
-
- HANDLE process_handles[MAX_PROCESSES];
- HANDLE process_kill_events[MAX_PROCESSES];
-
-
- /* Create child process
- * Should only be one in this version of Apache for WIN32
- */
- while (remaining_children_to_start--) {
- if (create_process(pconf, process_handles, process_kill_events,
- &current_live_processes) < 0) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,
- "master_main: create child process failed. Exiting.");
- shutdown_pending = 1;
- goto die_now;
- }
- }
-
- restart_pending = shutdown_pending = 0;
-
- if (!strcasecmp(signal_arg, "runservice"))
- mpm_service_started();
-
- /* Wait for shutdown or restart events or for child death */
- process_handles[current_live_processes] = shutdown_event;
- process_handles[current_live_processes+1] = restart_event;
-
- rv = WaitForMultipleObjects(current_live_processes+2, (HANDLE *)process_handles,
- FALSE, INFINITE);
- cld = rv - WAIT_OBJECT_0;
- if (rv == WAIT_FAILED) {
- /* Something serious is wrong */
- ap_log_error(APLOG_MARK,APLOG_CRIT, apr_get_os_error(), server_conf,
- "master_main: WaitForMultipeObjects WAIT_FAILED -- doing server shutdown");
- shutdown_pending = 1;
- }
- else if (rv == WAIT_TIMEOUT) {
- /* Hey, this cannot happen */
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,
- "master_main: WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");
- shutdown_pending = 1;
- }
- else if (cld == current_live_processes) {
- /* shutdown_event signalled */
- shutdown_pending = 1;
- printf("shutdown event signaled\n");
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, s,
- "Parent: SHUTDOWN EVENT SIGNALED -- Shutting down the server.");
- if (ResetEvent(shutdown_event) == 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,
- "ResetEvent(shutdown_event)");
- }
-
- }
- else if (cld == current_live_processes+1) {
- /* restart_event signalled */
- int children_to_kill = current_live_processes;
- restart_pending = 1;
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s,
- "Parent: RESTART EVENT SIGNALED -- Restarting the server.");
- if (ResetEvent(restart_event) == 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,
- "master_main: ResetEvent(restart_event) failed.");
- }
- /* Signal each child process to die
- * We are making a big assumption here that the child process, once signaled,
- * will REALLY go away. Since this is a restart, we do not want to hold the
- * new child process up waiting for the old child to die. Remove the old
- * child out of the process_handles apr_table_t and hope for the best...
- */
- for (i = 0; i < children_to_kill; i++) {
- if (SetEvent(process_kill_events[i]) == 0)
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,
- "master_main: SetEvent for child process in slot #%d failed", i);
- cleanup_process(process_handles, process_kill_events, i, &current_live_processes);
- }
- }
- else {
- /* A child process must have exited because of a fatal error condition (seg fault, etc.).
- * Remove the dead process
- * from the process_handles and process_kill_events apr_table_t and create a new
- * child process.
- * TODO: Consider restarting the child immediately without looping through http_main
- * and without rereading the configuration. Will need this if we ever support multiple
- * children. One option, create a parent thread which waits on child death and restarts it.
- * Consider, however, that if the user makes httpd.conf invalid, we want to die before
- * our child tries it... otherwise we have a nasty loop.
- */
- restart_pending = 1;
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, server_conf,
- "Parent: CHILD PROCESS FAILED -- Restarting the child process.");
- ap_assert(cld < current_live_processes);
- cleanup_process(process_handles, process_kill_events, cld, &current_live_processes);
- /* APD2("main_process: child in slot %d died", rv); */
- /* restart_child(process_hancles, process_kill_events, cld, &current_live_processes); */
- }
-
-die_now:
- if (shutdown_pending)
- {
- int tmstart = time(NULL);
-
- if (strcasecmp(signal_arg, "runservice")) {
- mpm_service_stopping();
- }
- /* Signal each child processes to die */
- for (i = 0; i < current_live_processes; i++) {
- printf("SetEvent handle = %d\n", process_kill_events[i]);
- if (SetEvent(process_kill_events[i]) == 0)
- ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), server_conf,
- "master_main: SetEvent for child process in slot #%d failed", i);
- }
-
- while (current_live_processes && ((tmstart+60) > time(NULL))) {
- rv = WaitForMultipleObjects(current_live_processes, (HANDLE *)process_handles, FALSE, 2000);
- if (rv == WAIT_TIMEOUT)
- continue;
- ap_assert(rv != WAIT_FAILED);
- cld = rv - WAIT_OBJECT_0;
- ap_assert(rv < current_live_processes);
- cleanup_process(process_handles, process_kill_events, cld, &current_live_processes);
- }
- for (i = 0; i < current_live_processes; i++) {
- ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, APR_SUCCESS, server_conf,
- "Parent: Forcing termination of child #%d (handle %d)", i, process_handles[i]);
- TerminateProcess((HANDLE) process_handles[i], 1);
- }
- return 0; /* Tell the caller we do not want to restart */
- }
-
- return 1; /* Tell the caller we want a restart */
-}
-
-
-/* service_nt_main_fn needs to append the StartService() args
- * outside of our call stack and thread as the service starts...
- */
-apr_array_header_t *mpm_new_argv;
-
-/* Remember service_to_start failures to log and fail in pre_config.
- * Remember inst_argc and inst_argv for installing or starting the
- * service after we preflight the config.
- */
-
-AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
-{
- switch(query_code){
- case AP_MPMQ_MAX_DAEMONS:
- *result = MAXIMUM_WAIT_OBJECTS;
- return APR_SUCCESS;
- case AP_MPMQ_IS_THREADED:
- *result = AP_MPMQ_STATIC;
- return APR_SUCCESS;
- case AP_MPMQ_IS_FORKED:
- *result = AP_MPMQ_NOT_SUPPORTED;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_DAEMONS:
- *result = HARD_SERVER_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_HARD_LIMIT_THREADS:
- *result = HARD_THREAD_LIMIT;
- return APR_SUCCESS;
- case AP_MPMQ_MAX_THREADS:
- *result = ap_threads_per_child;
- return APR_SUCCESS;
- }
- return APR_ENOTIMPL;
-}
-
-#define SERVICE_UNSET (-1)
-static apr_status_t service_set = SERVICE_UNSET;
-static apr_status_t service_to_start_success;
-static int inst_argc;
-static const char * const *inst_argv;
-static char *service_name = NULL;
-
-void winnt_rewrite_args(process_rec *process)
-{
- /* Handle the following SCM aspects in this phase:
- *
- * -k runservice [transition for WinNT, nothing for Win9x]
- * -k (!)install [error out if name is not installed]
- *
- * We can't leave this phase until we know our identity
- * and modify the command arguments appropriately.
- */
- apr_status_t rv;
- char *def_server_root;
- char fnbuf[MAX_PATH];
- char optbuf[3];
- const char *optarg;
- int fixed_args;
- char *pid;
- apr_getopt_t *opt;
- int running_as_service = 1;
-
- osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&osver);
-
- /* AP_PARENT_PID is only valid in the child */
- pid = getenv("AP_PARENT_PID");
- if (pid)
- {
- /* This is the child */
- my_pid = GetCurrentProcessId();
- parent_pid = (DWORD) atol(pid);
-
- /* The parent is responsible for providing the
- * COMPLETE ARGUMENTS REQUIRED to the child.
- *
- * No further argument parsing is needed, but
- * for good measure we will provide a simple
- * signal string for later testing.
- */
- signal_arg = "runchild";
- return;
- }
-
- /* This is the parent, we have a long way to go :-) */
- parent_pid = my_pid = GetCurrentProcessId();
-
- /* Rewrite process->argv[];
- *
- * strip out -k signal into signal_arg
- * strip out -n servicename and set the names
- * add default -d serverroot from the path of this executable
- *
- * The end result will look like:
- *
- * The invocation command (%0)
- * The -d serverroot default from the running executable
- * The requested service's (-n) registry ConfigArgs
- * The WinNT SCM's StartService() args
- */
- if (!GetModuleFileName(NULL, fnbuf, sizeof(fnbuf))) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK,APLOG_ERR, rv, NULL,
- "Failed to get the path of Apache.exe");
- exit(1);
- }
- /* WARNING: There is an implict assumption here that the
- * executable resides in ServerRoot or ServerRoot\bin
- */
- def_server_root = (char *) apr_filename_of_pathname(fnbuf);
- if (def_server_root > fnbuf) {
- *(def_server_root - 1) = '\0';
- def_server_root = (char *) apr_filename_of_pathname(fnbuf);
- if (!strcasecmp(def_server_root, "bin"))
- *(def_server_root - 1) = '\0';
- }
- def_server_root = ap_os_canonical_filename(process->pool, fnbuf);
-
- /* Use process->pool so that the rewritten argv
- * lasts for the lifetime of the server process,
- * because pconf will be destroyed after the
- * initial pre-flight of the config parser.
- */
- mpm_new_argv = apr_array_make(process->pool, process->argc + 2,
- sizeof(const char *));
- *(const char **)apr_array_push(mpm_new_argv) = process->argv[0];
- *(const char **)apr_array_push(mpm_new_argv) = "-d";
- *(const char **)apr_array_push(mpm_new_argv) = def_server_root;
-
- fixed_args = mpm_new_argv->nelts;
-
- optbuf[0] = '-';
- optbuf[2] = '\0';
- apr_getopt_init(&opt, process->pool, process->argc, (char**) process->argv);
- while (apr_getopt(opt, "n:k:iu" AP_SERVER_BASEARGS,
- optbuf + 1, &optarg) == APR_SUCCESS) {
- switch (optbuf[1]) {
- case 'n':
- service_set = mpm_service_set_name(process->pool, &service_name,
- optarg);
- break;
- case 'k':
- signal_arg = optarg;
- break;
- case 'i':
- ap_log_error(APLOG_MARK,APLOG_WARNING, 0, NULL,
- "-i is deprecated. Use -k install.");
- signal_arg = "install";
- break;
- case 'u':
- ap_log_error(APLOG_MARK,APLOG_WARNING, 0, NULL,
- "-u is deprecated. Use -k uninstall.");
- signal_arg = "uninstall";
- break;
- default:
- *(const char **)apr_array_push(mpm_new_argv) =
- apr_pstrdup(process->pool, optbuf);
-
- if (optarg) {
- *(const char **)apr_array_push(mpm_new_argv) = optarg;
- }
- break;
- }
- }
-
- /* Track the number of args actually entered by the user */
- inst_argc = mpm_new_argv->nelts - fixed_args;
-
- /* Provide a default 'run' -k arg to simplify signal_arg tests */
- if (!signal_arg)
- {
- signal_arg = "run";
- running_as_service = 0;
- }
-
- if (!strcasecmp(signal_arg, "runservice"))
- {
- /* Start the NT Service _NOW_ because the WinNT SCM is
- * expecting us to rapidly assume control of our own
- * process, the SCM will tell us our service name, and
- * may have extra StartService() command arguments to
- * add for us.
- *
- * Any other process has a console, so we don't to begin
- * a Win9x service until the configuration is parsed and
- * any command line errors are reported.
- *
- * We hold the return value so that we can die in pre_config
- * after logging begins, and the failure can land in the log.
- */
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- service_to_start_success = mpm_service_to_start(&service_name);
- if (service_to_start_success == APR_SUCCESS)
- service_set = APR_SUCCESS;
- }
- }
-
- if (service_set == SERVICE_UNSET && running_as_service) {
- service_set = mpm_service_set_name(process->pool, &service_name,
- DEFAULT_SERVICE_NAME);
- }
-
- if (!strcasecmp(signal_arg, "install")) /* -k install */
- {
- if (service_set == APR_SUCCESS)
- {
- ap_log_error(APLOG_MARK,APLOG_ERR, 0, NULL,
- "%s: Service is already installed.", service_name);
- exit(1);
- }
- }
- else if (running_as_service)
- {
- if (service_set == APR_SUCCESS)
- {
- rv = mpm_merge_service_args(process->pool, mpm_new_argv,
- fixed_args);
- if (rv == APR_SUCCESS) {
- ap_log_error(APLOG_MARK,APLOG_NOERRNO|APLOG_INFO, 0, NULL,
- "Using ConfigArgs of the installed service "
- "\"%s\".", service_name);
- }
- else {
- ap_log_error(APLOG_MARK,APLOG_INFO, rv, NULL,
- "No installed ConfigArgs for the service "
- "\"%s\", using Apache defaults.", service_name);
- }
- }
- else
- {
- ap_log_error(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO, 0, NULL,
- "No installed service named \"%s\".", service_name);
- exit(1);
- }
- }
-
- /* Track the args actually entered by the user.
- * These will be used for the -k install parameters, as well as
- * for the -k start service override arguments.
- */
- inst_argv = (const char * const *)mpm_new_argv->elts
- + mpm_new_argv->nelts - inst_argc;
-
- process->argc = mpm_new_argv->nelts;
- process->argv = (const char * const *) mpm_new_argv->elts;
-}
-
-
-static void winnt_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- /* Handle the following SCM aspects in this phase:
- *
- * -k runservice [WinNT errors logged from rewrite_args]
- * -k uninstall
- * -k stop
- *
- * in these cases we -don't- care if httpd.conf has config errors!
- */
- apr_status_t rv;
-
- if (ap_exists_config_define("ONE_PROCESS"))
- one_process = -1;
-
- if (ap_exists_config_define("ONE_PROCESS"))
- one_process = -1;
-
- if (!strcasecmp(signal_arg, "runservice")
- && (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- && (service_to_start_success != APR_SUCCESS)) {
- ap_log_error(APLOG_MARK,APLOG_ERR, service_to_start_success, NULL,
- "%s: Unable to start the service manager.",
- service_name);
- exit(1);
- }
-
- if (!strcasecmp(signal_arg, "uninstall")) {
- rv = mpm_service_uninstall();
- exit(rv);
- }
-
- if (!strcasecmp(signal_arg, "stop")) {
- mpm_signal_service(ptemp, 0);
- exit(0);
- }
-
- ap_listen_pre_config();
- ap_daemons_to_start = DEFAULT_NUM_DAEMON;
- ap_threads_per_child = DEFAULT_START_THREAD;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
-}
-
-static void winnt_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec* server)
-{
- static int restart_num = 0;
- apr_status_t rv = 0;
-
- server_conf = server;
-
- /* Handle the following SCM aspects in this phase:
- *
- * -k install
- * -k start
- * -k restart
- * -k runservice [Win95, only once - after we parsed the config]
- *
- * because all of these signals are useful _only_ if there
- * is a valid conf\httpd.conf environment to start.
- *
- * We reached this phase by avoiding errors that would cause
- * these options to fail unexpectedly in another process.
- */
-
- if (!strcasecmp(signal_arg, "install")) {
- rv = mpm_service_install(ptemp, inst_argc, inst_argv);
- exit (rv);
- }
-
- if (!strcasecmp(signal_arg, "start")) {
- rv = mpm_service_start(ptemp, inst_argc, inst_argv);
- exit (rv);
- }
-
- if (!strcasecmp(signal_arg, "restart")) {
- mpm_signal_service(ptemp, 1);
- exit (rv);
- }
-
- if (parent_pid == my_pid)
- {
- if (restart_num++ == 1)
- {
- /* This code should be run once in the parent and not run
- * across a restart
- */
- PSECURITY_ATTRIBUTES sa = GetNullACL(); /* returns NULL if invalid (Win95?) */
- setup_signal_names(apr_psprintf(pconf,"ap%d", parent_pid));
-
- ap_log_pid(pconf, ap_pid_fname);
-
- /* Create shutdown event, apPID_shutdown, where PID is the parent
- * Apache process ID. Shutdown is signaled by 'apache -k shutdown'.
- */
- shutdown_event = CreateEvent(sa, FALSE, FALSE, signal_shutdown_name);
- if (!shutdown_event) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), server_conf,
- "Parent: Cannot create shutdown event %s", signal_shutdown_name);
- CleanNullACL((void *)sa);
- exit(1);
- }
-
- /* Create restart event, apPID_restart, where PID is the parent
- * Apache process ID. Restart is signaled by 'apache -k restart'.
- */
- restart_event = CreateEvent(sa, FALSE, FALSE, signal_restart_name);
- if (!restart_event) {
- CloseHandle(shutdown_event);
- ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), server_conf,
- "Parent: Cannot create restart event %s", signal_restart_name);
- CleanNullACL((void *)sa);
- exit(1);
- }
- CleanNullACL((void *)sa);
-
- /* Now that we are flying at 15000 feet...
- * wipe out the Win95 service console,
- * signal the SCM the WinNT service started, or
- * if not a service, setup console handlers instead.
- */
- if (!strcasecmp(signal_arg, "runservice"))
- {
- if (osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
- {
- rv = mpm_service_to_start(&service_name);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK,APLOG_ERR, rv, server_conf,
- "%s: Unable to start the service manager.",
- service_name);
- exit(1);
- }
- }
- }
- else /* ! -k runservice */
- {
- mpm_start_console_handler();
- }
-
- /* Create the start mutex, apPID, where PID is the parent Apache process ID.
- * Ths start mutex is used during a restart to prevent more than one
- * child process from entering the accept loop at once.
- */
- apr_lock_create(&start_mutex,APR_MUTEX, APR_CROSS_PROCESS, signal_name_prefix,
- server_conf->process->pool);
- }
- }
- else /* parent_pid != my_pid */
- {
- mpm_start_child_console_handler();
- }
-}
-
-AP_DECLARE(int) ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s )
-{
- static int restart = 0; /* Default is "not a restart" */
-
- pconf = _pconf;
- server_conf = s;
-
- if ((parent_pid != my_pid) || one_process) {
- /* Child process or in one_process (debug) mode */
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Child process is running", my_pid);
-
- /* Set up the scoreboard. The scoreboard in this MPM only applies to the
- * child process and is not shared across processes
- */
- ap_create_scoreboard(pconf, SB_NOT_SHARED);
-
- if (one_process) {
- if (ap_setup_listeners(server_conf) < 1) {
- return 1;
- }
- }
- else {
- get_listeners_from_parent(server_conf);
- }
-
- child_main();
-
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,
- "Child %d: Child process is exiting", my_pid);
-
- return 1;
- }
- else {
- /* Parent process */
- if (ap_setup_listeners(server_conf) < 1) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
- "no listening sockets available, shutting down");
- return 1;
- }
-
- restart = master_main(server_conf, shutdown_event, restart_event);
-
- if (!restart) {
- /* Shutting down. Clean up... */
- const char *pidfile = ap_server_root_relative (pconf, ap_pid_fname);
-
- if (pidfile != NULL && unlink(pidfile) == 0) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS,
- server_conf, "removed PID file %s (pid=%ld)",
- pidfile, GetCurrentProcessId());
- }
- apr_lock_destroy(start_mutex);
-
- CloseHandle(restart_event);
- CloseHandle(shutdown_event);
-
- return 1;
- }
- } /* Parent process */
-
- return 0; /* Restart */
-}
-
-static void winnt_hooks(apr_pool_t *p)
-{
- ap_hook_pre_config(winnt_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(winnt_post_config, NULL, NULL, 0);
-}
-
-/*
- * Command processors
- */
-static const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- if (cmd->server->is_virtual) {
- return "PidFile directive not allowed in <VirtualHost>";
- }
- ap_pid_fname = arg;
- return NULL;
-}
-
-static const char *set_threads_per_child (cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_threads_per_child = atoi(arg);
- if (ap_threads_per_child > HARD_THREAD_LIMIT) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: ThreadsPerChild of %d exceeds compile time"
- " limit of %d threads,", ap_threads_per_child,
- HARD_THREAD_LIMIT);
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " lowering ThreadsPerChild to %d. To increase, please"
- " see the HARD_THREAD_LIMIT define in %s.",
- HARD_THREAD_LIMIT, AP_MPM_HARD_LIMITS_FILE);
- ap_threads_per_child = HARD_THREAD_LIMIT;
- }
- else if (ap_threads_per_child < 1) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "WARNING: Require ThreadsPerChild > 0, setting to 1");
- ap_threads_per_child = 1;
- }
- return NULL;
-}
-
-
-static const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- ap_max_requests_per_child = atoi(arg);
-
- return NULL;
-}
-
-static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg)
-{
- apr_finfo_t finfo;
- const char *fname;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
-
- fname = ap_server_root_relative(cmd->pool, arg);
- if ((apr_stat(&finfo, fname, APR_FINFO_TYPE, cmd->pool) != APR_SUCCESS)
- || (finfo.filetype != APR_DIR)) {
- return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
- " does not exist or is not a directory", NULL);
- }
- apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
- return NULL;
-}
-
-/* Stub functions until this MPM supports the connection status API */
-
-AP_DECLARE(void) ap_update_connection_status(long conn_id, const char *key, \
- const char *value)
-{
- /* NOP */
-}
-
-AP_DECLARE(void) ap_reset_connection_status(long conn_id)
-{
- /* NOP */
-}
-
-AP_DECLARE(apr_array_header_t *) ap_get_status_table(apr_pool_t *p)
-{
- /* NOP */
- return NULL;
-}
-
-static const command_rec winnt_cmds[] = {
-LISTEN_COMMANDS
-{ "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
- "A file for logging the server process ID"},
-{ "ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF, TAKE1,
- "Number of threads each child creates" },
-{ "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
- "Maximum number of requests a particular child serves before dying." },
-{ "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
- "The location of the directory Apache changes to before dumping core" },
-{ NULL }
-};
-
-AP_MODULE_DECLARE_DATA module mpm_winnt_module = {
- MPM20_MODULE_STUFF,
- winnt_rewrite_args, /* hook to run before apache parses args */
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- winnt_cmds, /* command apr_table_t */
- winnt_hooks /* register_hooks */
-};
diff --git a/server/mpm/winnt/mpm_winnt.h b/server/mpm/winnt/mpm_winnt.h
deleted file mode 100644
index cec0a64ce4..0000000000
--- a/server/mpm/winnt/mpm_winnt.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef APACHE_MPM_WINNT_H
-#define APACHE_MPM_WINNT_H
-
-#include "ap_listen.h"
-
-/* From registry.c: */
-
-apr_status_t ap_registry_create_key(const char *key);
-apr_status_t ap_registry_delete_key(const char *key);
-
-apr_status_t ap_registry_store_value(const char *key, const char *name,
- const char *value);
-apr_status_t ap_registry_get_value(apr_pool_t *p, const char *key,
- const char *name, char **ppValue);
-apr_status_t ap_registry_store_array(apr_pool_t *p, const char *key,
- const char *name, int nelts,
- char const* const* elts);
-apr_status_t ap_registry_get_array(apr_pool_t *p, const char *key,
- const char *name,
- apr_array_header_t **parray);
-apr_status_t ap_registry_delete_value(const char *key, const char *name);
-
-
-/* From service.c: */
-
-#define SERVICE_APACHE_RESTART 128
-
-#define DEFAULT_SERVICE_NAME AP_SERVER_BASEPRODUCT
-#define SERVICECONFIG9X "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"
-#define SERVICECONFIG "System\\CurrentControlSet\\Services\\%s"
-#define SERVICEPARAMS "System\\CurrentControlSet\\Services\\%s\\Parameters"
-
-apr_status_t mpm_service_set_name(apr_pool_t *p, const char **display_name,
- const char *set_name);
-apr_status_t mpm_merge_service_args(apr_pool_t *p, apr_array_header_t *args,
- int fixed_args);
-
-apr_status_t mpm_service_to_start(const char **display_name);
-apr_status_t mpm_service_started(void);
-apr_status_t mpm_service_install(apr_pool_t *ptemp, int argc,
- char const* const* argv);
-apr_status_t mpm_service_uninstall(void);
-
-apr_status_t mpm_service_start(apr_pool_t *ptemp, int argc,
- char const* const* argv);
-
-void mpm_signal_service(apr_pool_t *ptemp, int signal);
-
-void mpm_service_stopping(void);
-
-void mpm_start_console_handler(void);
-void mpm_start_child_console_handler(void);
-
-/* From winnt.c: */
-
-extern OSVERSIONINFO osver;
-extern int ap_max_requests_per_child;
-extern void clean_child_exit(int);
-
-AP_DECLARE(void) ap_start_shutdown(void);
-AP_DECLARE(void) ap_start_restart(int gracefully);
-
-void setup_signal_names(char *prefix);
-void signal_parent(int type);
-
-
-/* This code is stolen from the apr_private.h and misc/win32/misc.c
- * Please see those sources for detailed documentation.
- */
-typedef enum {
- DLL_WINBASEAPI = 0, // kernel32 From WinBase.h
- DLL_WINADVAPI = 1, // advapi32 From WinBase.h
- DLL_WINSOCKAPI = 2, // mswsock From WinSock.h
- DLL_WINSOCK2API = 3, // ws2_32 From WinSock2.h
- DLL_defined = 4 // must define as last idx_ + 1
-} ap_dlltoken_e;
-
-FARPROC ap_load_dll_func(ap_dlltoken_e fnLib, char *fnName, int ordinal);
-
-#define AP_DECLARE_LATE_DLL_FUNC(lib, rettype, calltype, fn, ord, args, names) \
- typedef rettype (calltype *ap_winapi_fpt_##fn) args; \
- static ap_winapi_fpt_##fn ap_winapi_pfn_##fn = NULL; \
- __inline rettype ap_winapi_##fn args \
- { if (!ap_winapi_pfn_##fn) \
- ap_winapi_pfn_##fn = (ap_winapi_fpt_##fn) ap_load_dll_func(lib, #fn, ord); \
- return (*(ap_winapi_pfn_##fn)) names; }; \
-
-/* WinNT kernel only */
-AP_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, CancelIo, 0, (
- IN HANDLE hFile),
- (hFile));
-#define CancelIo ap_winapi_CancelIo
-
-/* Win9x kernel only */
-AP_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, DWORD, WINAPI, RegisterServiceProcess, 0, (
- DWORD dwProcessId,
- DWORD dwType),
- (dwProcessId, dwType));
-#define RegisterServiceProcess ap_winapi_RegisterServiceProcess
-
-#endif /* APACHE_MPM_WINNT_H */
diff --git a/server/mpm/winnt/registry.c b/server/mpm/winnt/registry.c
deleted file mode 100644
index aa23e54a4d..0000000000
--- a/server/mpm/winnt/registry.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * Functions to handle interacting with the Win32 registry
- */
-
-/*
- * Apache registry key structure
- *
- * Apache's registry information is stored in the HKEY_LOCAL_MACHINE
- * key, under
- *
- * HKLM\SOFTWARE\Apache Software Foundation\Apache\version
- *
- * These keys are defined in this file. The definition of the "version" part
- * will need updating each time Apache moves from beta to non-beta or from a
- * release to a development or beta version.
- */
-
-#include "httpd.h"
-#include "http_log.h"
-#include "mpm_winnt.h"
-#include "apr_strings.h"
-
-/* bet you are looking to change revisions to roll the tarball...
- * Guess what, you already did. Revised May '00 to save you from
- * searching all over creation for every revision tag.
- */
-
-#define VENDOR AP_SERVER_BASEVENDOR
-#define SOFTWARE AP_SERVER_BASEPRODUCT
-#define VERSION AP_SERVER_BASEREVISION
-
-#define REGKEY "SOFTWARE\\" VENDOR "\\" SOFTWARE "\\" VERSION
-
-/*
- * The Windows API registry key functions don't set the last error
- * value (the windows equivalent of errno). So we need to set it
- * with SetLastError() before calling the aplog_error() function.
- * Because this is common, let's have a macro.
- */
-#define return_error(rv) return (apr_set_os_error(APR_FROM_OS_ERROR(rv)),\
- APR_FROM_OS_ERROR(rv));
-
-apr_status_t ap_registry_create_key(const char *key)
-{
- HKEY hKey = HKEY_LOCAL_MACHINE;
- HKEY hKeyNext;
- char keystr[MAX_PATH + 1];
- char *parsekey = keystr;
- char *nextkey = keystr;
- DWORD result;
- int rv;
-
- apr_cpystrn(keystr, key, sizeof(keystr) - 1);
-
- /* Walk the tree, creating at each stage if necessary */
- while (parsekey) {
- if (nextkey = strchr(parsekey, '\\'))
- *(nextkey++) = '\0';
-
- rv = RegCreateKeyEx(hKey,
- parsekey, /* subkey */
- 0, /* reserved */
- NULL, /* class */
- REG_OPTION_NON_VOLATILE,
- KEY_WRITE,
- NULL,
- &hKeyNext,
- &result);
-
- /* Close the old key */
- if (hKey != HKEY_LOCAL_MACHINE)
- RegCloseKey(hKey);
- hKey = hKeyNext;
-
- if (rv != ERROR_SUCCESS)
- break;
-
- parsekey = nextkey;
- }
-
- if (hKey != HKEY_LOCAL_MACHINE)
- RegCloseKey(hKey);
-
- return_error(rv);
-}
-
-apr_status_t ap_registry_delete_key(const char *key)
-{
- apr_status_t rv;
- HKEY hKey;
- int nSize = 0;
- char tempkey[MAX_PATH + 1];
- char *parsekey;
-
- apr_cpystrn(tempkey, key, sizeof(parsekey) - 1);
- parsekey = strrchr(tempkey, '\\');
-
- if (parsekey) {
- *(parsekey++) = '\0';
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- tempkey,
- 0,
- KEY_WRITE,
- &hKey);
-
- if (rv != ERROR_SUCCESS)
- return_error(rv);
- }
- else {
- parsekey = tempkey;
- hKey = HKEY_LOCAL_MACHINE;
- }
-
- rv = RegDeleteKey(hKey, key);
-
- if (hKey != HKEY_LOCAL_MACHINE)
- RegCloseKey(hKey);
-
- return_error(rv);
-}
-
-/* Clean up a way over complicated process.
- *
- * The return value is APR_SUCCESS, APR_ENOENT, APR_NOTFOUND, or the OS error
- */
-
-apr_status_t ap_registry_get_value(apr_pool_t *p, const char *key, const char *name, char **ppValue)
-{
- apr_status_t rv;
- HKEY hKey;
- int nSize = 0;
-
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- key,
- 0,
- KEY_READ,
- &hKey);
-
- if (rv != ERROR_SUCCESS)
- return_error(rv);
-
- /* Find the size required for the data by passing NULL as the buffer
- * pointer. On return nSize will contain the size required for the
- * buffer if the return value is ERROR_SUCCESS.
- */
- rv = RegQueryValueEx(hKey,
- name, /* key name */
- NULL, /* reserved */
- NULL, /* type */
- NULL, /* for value */
- &nSize); /* for size of "value" */
-
- if (rv != ERROR_SUCCESS)
- return_error(rv);
-
- *ppValue = apr_palloc(p, nSize);
- rv = RegQueryValueEx(hKey,
- name, /* key name */
- NULL, /* reserved */
- NULL, /* type */
- *ppValue, /* for value */
- &nSize); /* for size of "value" */
-
- RegCloseKey(hKey);
-
- return_error(rv);
-}
-
-apr_status_t ap_registry_get_array(apr_pool_t *p, const char *key, const char *name, apr_array_header_t **parray)
-{
- char *pValue;
- char *tmp;
- char **newelem;
- apr_status_t rv;
- HKEY hKey;
- int nSize = 0;
-
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- key,
- 0,
- KEY_READ,
- &hKey);
-
- if (rv != ERROR_SUCCESS)
- return_error(rv);
-
- /* Find the size required for the data by passing NULL as the buffer
- * pointer. On return nSize will contain the size required for the
- * buffer if the return value is ERROR_SUCCESS.
- */
- rv = RegQueryValueEx(hKey,
- name, /* key name */
- NULL, /* reserved */
- NULL, /* type */
- NULL, /* for value */
- &nSize); /* for size of "value" */
-
- if (rv != ERROR_SUCCESS) {
- return_error(rv);
- }
- else
- {
- pValue = apr_palloc(p, nSize);
- rv = RegQueryValueEx(hKey,
- name, /* key name */
- NULL, /* reserved */
- NULL, /* type */
- pValue, /* for value */
- &nSize); /* for size of "value" */
-
- nSize = 1; /* Element Count */
- tmp = pValue;
- while (tmp[0] || tmp[1])
- {
- if (!tmp[0])
- ++nSize;
- ++tmp;
- }
-
- *parray = apr_array_make(p, nSize, sizeof(char *));
- tmp = pValue;
- newelem = (char **) apr_array_push(*parray);
- *newelem = tmp;
- while (tmp[0] || tmp[1])
- {
- if (!tmp[0]) {
- newelem = (char **) apr_array_push(*parray);
- *newelem = tmp + 1;
- }
- ++tmp;
- }
- }
-
- RegCloseKey(hKey);
-
- return_error(rv);
-}
-
-/*
- * ap_registry_store_key_value() stores a value name and value under the
- * Apache registry key. If the Apache key does not exist it is created
- * first. This function is intended to be called from a wrapper function
- * in this file to set particular data values, such as
- * ap_registry_set_server_root() below.
- *
- * Returns 0 if the value name and data was stored successfully, or
- * returns -1 if the Apache key does not exist (since we try to create
- * this key, this should never happen), or -4 if any other error occurred
- * (these values are consistent with ap_registry_get_key_value()).
- * If the return value is negative then the error will already have been
- * logged via aplog_error().
- */
-
-apr_status_t ap_registry_store_value(const char *key, const char *name, const char *value)
-{
- long rv;
- HKEY hKey;
-
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- key,
- 0,
- KEY_WRITE,
- &hKey);
-
- if (rv == ERROR_FILE_NOT_FOUND)
- {
- rv = ap_registry_create_key(key);
-
- if (rv != APR_SUCCESS)
- return_error(rv);
-
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- key,
- 0,
- KEY_WRITE,
- &hKey);
- }
-
- if (rv != ERROR_SUCCESS)
- return_error(rv);
-
- /* Now set the value and data */
- rv = RegSetValueEx(hKey,
- name, /* value key name */
- 0, /* reserved */
- REG_SZ, /* type */
- value, /* value data */
- (DWORD) strlen(value) + 1); /* for size of "value" */
-
- if (rv == ERROR_SUCCESS) {
- ap_log_error(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,rv,NULL,
- "Registry stored HKLM\\" REGKEY "\\%s value %s", key, value);
- }
-
- /* Make sure we close the key even if there was an error storing
- * the data
- */
- RegCloseKey(hKey);
-
- return_error(rv);
-}
-
-apr_status_t ap_registry_store_array(apr_pool_t *p,
- const char *key, const char *name,
- int nelts, const char * const * elts)
-{
- int bufsize, i;
- char *buf, *tmp;
- long rv;
- HKEY hKey;
-
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- key,
- 0,
- KEY_WRITE,
- &hKey);
-
- if (rv == ERROR_FILE_NOT_FOUND)
- {
- rv = ap_registry_create_key(key);
-
- if (rv != APR_SUCCESS)
- return_error(rv);
-
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- key,
- 0,
- KEY_WRITE,
- &hKey);
- }
-
- if (rv != ERROR_SUCCESS)
- return_error(rv);
-
- bufsize = 1; /* For trailing second null */
- for (i = 0; i < nelts; ++i)
- {
- bufsize += strlen(elts[i]) + 1;
- }
- if (!nelts)
- ++bufsize;
-
- buf = apr_palloc(p, bufsize);
- tmp = buf;
- for (i = 0; i < nelts; ++i)
- {
- strcpy(tmp, elts[i]);
- tmp += strlen(elts[i]) + 1;
- }
- if (!nelts)
- (*tmp++) = '\0';
- *tmp = '\0'; /* Trailing second null */
-
- /* Now set the value and data */
- rv = RegSetValueEx(hKey,
- name, /* value key name */
- 0, /* reserved */
- REG_MULTI_SZ, /* type */
- buf, /* value data */
- (DWORD) bufsize); /* for size of "value" */
-
- if (rv == ERROR_SUCCESS) {
- ap_log_error(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,rv,NULL,
- "Registry stored HKLM\\" REGKEY "\\%s", key);
- }
-
- /* Make sure we close the key even if there was an error storing
- * the data
- */
- RegCloseKey(hKey);
-
- return_error(rv);
-}
-
-/* A key or value that does not exist is _not_ an error while deleting. */
-
-apr_status_t ap_registry_delete_value(const char *key, const char *name)
-{
- apr_status_t rv;
- HKEY hKey;
-
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- key,
- 0,
- KEY_WRITE,
- &hKey);
-
- if (rv == ERROR_FILE_NOT_FOUND)
- return APR_SUCCESS;
-
- if (rv != ERROR_SUCCESS)
- return_error(rv);
-
- rv = RegDeleteValue(hKey, name);
-
- if (rv == ERROR_FILE_NOT_FOUND)
- rv = APR_SUCCESS;
-
- RegCloseKey(hKey);
- return_error(rv);
-}
-
-/*
- * Get the server root from the registry into 'dir' which is
- * size bytes long. Returns 0 if the server root was found
- * or if the serverroot key does not exist (in which case
- * dir will contain an empty string), or -1 if there was
- * an error getting the key.
- */
-apr_status_t ap_registry_get_server_root(apr_pool_t *p, char **buf)
-{
- apr_status_t rv;
-
- rv = ap_registry_get_value(p, REGKEY, "ServerRoot", buf);
- if (rv)
- *buf = NULL;
-
- return rv;
-}
-
-
-/*
- * Sets the serverroot value within the registry. Returns 0 on success
- * or -1 on error. If -1 is return the error will already have been
- * logged via aplog_error().
- */
-
-apr_status_t ap_registry_set_server_root(char *dir)
-{
- return ap_registry_store_value(REGKEY, "ServerRoot", dir);
-}
diff --git a/server/mpm/winnt/service.c b/server/mpm/winnt/service.c
deleted file mode 100644
index ac88e236c4..0000000000
--- a/server/mpm/winnt/service.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* This module ALONE requires the window message API from user.h
- * and the default APR include of windows.h will omit it, so
- * preload the API symbols now...
- */
-
-#define CORE_PRIVATE
-#define _WINUSER_
-
-#include "httpd.h"
-#include "http_log.h"
-#include "mpm_winnt.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#ifdef NOUSER
-#undef NOUSER
-#endif
-#undef _WINUSER_
-#include <winuser.h>
-
-static char *mpm_service_name = NULL;
-static char *mpm_display_name = NULL;
-
-static struct
-{
- HANDLE mpm_thread; /* primary thread handle of the apache server */
- HANDLE service_thread; /* thread service/monitor handle */
- DWORD service_thread_id;/* thread service/monitor ID */
- HANDLE signal_monitor; /* service monitor thread signal event */
- SERVICE_STATUS ssStatus;
- SERVICE_STATUS_HANDLE hServiceStatus;
-} globdat;
-
-static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint);
-
-/* The service configuration's is stored under the following trees:
- *
- * HKLM\System\CurrentControlSet\Services\[service name]
- *
- * \DisplayName
- * \ImagePath (NT Only)
- * \Parameters\ConfigArgs
- *
- * For Win9x, the launch service command is stored under:
- *
- * HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices\[service name]
- */
-
-
-/* exit() for Win32 is macro mapped (horrible, we agree) that allows us
- * to catch the non-zero conditions and inform the console process that
- * the application died, and hang on to the console a bit longer.
- *
- * The macro only maps for http_main.c and other sources that include
- * the service.h header, so we best assume it's an error to exit from
- * _any_ other module.
- *
- * If real_exit_code is reset to 0, it will not be set or trigger this
- * behavior on exit. All service and child processes are expected to
- * reset this flag to zero to avoid undesireable side effects.
- */
-int real_exit_code = 1;
-
-void hold_console_open_on_error(void)
-{
- HANDLE hConIn;
- HANDLE hConErr;
- DWORD result;
- time_t start;
- time_t remains;
- char *msg = "Note the errors or messages above, "
- "and press the <ESC> key to exit. ";
- CONSOLE_SCREEN_BUFFER_INFO coninfo;
- INPUT_RECORD in;
- char count[16];
-
- if (!real_exit_code)
- return;
- hConIn = GetStdHandle(STD_INPUT_HANDLE);
- hConErr = GetStdHandle(STD_ERROR_HANDLE);
- if ((hConIn == INVALID_HANDLE_VALUE) || (hConErr == INVALID_HANDLE_VALUE))
- return;
- if (!WriteConsole(hConErr, msg, strlen(msg), &result, NULL) || !result)
- return;
- if (!GetConsoleScreenBufferInfo(hConErr, &coninfo))
- return;
- if (!SetConsoleMode(hConIn, ENABLE_MOUSE_INPUT | 0x80))
- return;
-
- start = time(NULL);
- do
- {
- while (PeekConsoleInput(hConIn, &in, 1, &result) && result)
- {
- if (!ReadConsoleInput(hConIn, &in, 1, &result) || !result)
- return;
- if ((in.EventType == KEY_EVENT) && in.Event.KeyEvent.bKeyDown
- && (in.Event.KeyEvent.uChar.AsciiChar == 27))
- return;
- if (in.EventType == MOUSE_EVENT
- && (in.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
- return;
- }
- remains = ((start + 30) - time(NULL));
- sprintf (count, "%d...", remains);
- if (!SetConsoleCursorPosition(hConErr, coninfo.dwCursorPosition))
- return;
- if (!WriteConsole(hConErr, count, strlen(count), &result, NULL)
- || !result)
- return;
- }
- while ((remains > 0) && WaitForSingleObject(hConIn, 1000) != WAIT_FAILED);
-}
-
-static BOOL die_on_logoff = FALSE;
-
-static LRESULT CALLBACK monitor_service_9x_proc(HWND hWnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
-{
-/* This is the WndProc procedure for our invisible window.
- * When the user shuts down the system, this window is sent
- * a signal WM_ENDSESSION. We clean up by signaling Apache
- * to shut down, and idle until Apache's primary thread quits.
- */
- if ((msg == WM_ENDSESSION)
- && (die_on_logoff || (lParam != ENDSESSION_LOGOFF)))
- {
- signal_parent(0);
- if (wParam)
- /* Don't leave this message until we are dead! */
- WaitForSingleObject(globdat.mpm_thread, 30000);
- return 0;
- }
- return (DefWindowProc(hWnd, msg, wParam, lParam));
-}
-
-static DWORD WINAPI monitor_service_9x_thread(void *service_name)
-{
- /* When running as a service under Windows 9x, there is no console
- * window present, and no ConsoleCtrlHandler to call when the system
- * is shutdown. If the WatchWindow thread is created with a NULL
- * service_name argument, then the ...SystemMonitor window class is
- * used to create the "Apache" window to watch for logoff and shutdown.
- * If the service_name is provided, the ...ServiceMonitor window class
- * is used to create the window named by the service_name argument,
- * and the logoff message is ignored.
- */
- WNDCLASS wc;
- HWND hwndMain;
- MSG msg;
-
- wc.style = CS_GLOBALCLASS;
- wc.lpfnWndProc = monitor_service_9x_proc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = NULL;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- if (service_name)
- wc.lpszClassName = "ApacheWin95ServiceMonitor";
- else
- wc.lpszClassName = "ApacheWin95SystemMonitor";
-
- die_on_logoff = service_name ? FALSE : TRUE;
-
- if (!RegisterClass(&wc))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
- NULL, "Could not register window class for WatchWindow");
- SetEvent(globdat.signal_monitor);
- globdat.service_thread_id = 0;
- return 0;
- }
-
- /* Create an invisible window */
- hwndMain = CreateWindow(wc.lpszClassName,
- service_name ? (char *) service_name : "Apache",
- WS_OVERLAPPEDWINDOW & ~WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, NULL, NULL, NULL, NULL);
-
- if (!hwndMain)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
- NULL, "Could not create WatchWindow");
- SetEvent(globdat.signal_monitor);
- globdat.service_thread_id = 0;
- return 0;
- }
-
- /* If we succeed, eliminate the console window.
- * Signal the parent we are all set up, and
- * watch the message queue while the window lives.
- */
- FreeConsole();
- SetEvent((HANDLE) globdat.signal_monitor);
- while (GetMessage(&msg, NULL, 0, 0))
- {
- if (msg.message == WM_CLOSE)
- DestroyWindow(hwndMain);
- else {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- globdat.service_thread_id = 0;
- return 0;
-}
-
-
-static BOOL CALLBACK console_control_handler(DWORD ctrl_type)
-{
- switch (ctrl_type)
- {
- case CTRL_BREAK_EVENT:
- fprintf(stderr, "Apache server restarting...\n");
- signal_parent(1);
- return TRUE;
- case CTRL_C_EVENT:
- fprintf(stderr, "Apache server interrupted...\n");
- /* for Interrupt signals, shut down the server.
- * Tell the system we have dealt with the signal
- * without waiting for Apache to terminate.
- */
- signal_parent(0);
- return TRUE;
-
- case CTRL_CLOSE_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- /* for Terminate signals, shut down the server.
- * Wait for Apache to terminate, but respond
- * after a reasonable time to tell the system
- * that we did attempt to shut ourself down.
- * THESE EVENTS WILL NOT OCCUR UNDER WIN9x!
- */
- fprintf(stderr, "Apache server shutdown initiated...\n");
- signal_parent(0);
- Sleep(30000);
- return TRUE;
- }
-
- /* We should never get here, but this is (mostly) harmless */
- return FALSE;
-}
-
-
-static void stop_console_handler(void)
-{
- SetConsoleCtrlHandler(console_control_handler, FALSE);
-}
-
-
-void mpm_start_console_handler(void)
-{
- SetConsoleCtrlHandler(console_control_handler, TRUE);
- atexit(stop_console_handler);
-}
-
-
-/* Special situation - children of services need to mind their
- * P's & Q's and wait quietly, ignoring the mean OS signaling
- * shutdown and other horrors, to kill them gracefully...
- */
-
-static BOOL CALLBACK child_control_handler(DWORD ctrl_type)
-{
- switch (ctrl_type)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- /* for Interrupt signals, ignore them.
- * The system will also signal the parent process,
- * which will terminate Apache.
- */
- return TRUE;
-
- case CTRL_CLOSE_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- /* for Shutdown signals, ignore them, but... .
- * The system will also signal the parent process,
- * which will terminate Apache, so we need to wait.
- */
- Sleep(30000);
- return TRUE;
- }
-
- /* We should never get here, but this is (mostly) harmless */
- return FALSE;
-}
-
-
-static void stop_child_console_handler(void)
-{
- SetConsoleCtrlHandler(child_control_handler, FALSE);
-}
-
-
-void mpm_start_child_console_handler(void)
-{
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- FreeConsole();
- }
- else
- {
- SetConsoleCtrlHandler(child_control_handler, TRUE);
- atexit(stop_child_console_handler);
- }
-}
-
-
-/**********************************
- WinNT service control management
- **********************************/
-
-static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint)
-{
- static int checkPoint = 1;
- int rv = APR_SUCCESS;
-
- if (globdat.hServiceStatus)
- {
- if (currentState == SERVICE_RUNNING)
- globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- else
- globdat.ssStatus.dwControlsAccepted = 0;
-
- globdat.ssStatus.dwCurrentState = currentState;
- globdat.ssStatus.dwWin32ExitCode = exitCode;
-
- if ( ( currentState == SERVICE_RUNNING ) ||
- ( currentState == SERVICE_STOPPED ) )
- {
- globdat.ssStatus.dwWaitHint = 0;
- globdat.ssStatus.dwCheckPoint = 0;
- }
- else
- {
- if(waitHint)
- globdat.ssStatus.dwWaitHint = waitHint;
- globdat.ssStatus.dwCheckPoint = ++checkPoint;
- }
- rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus);
- }
- return(rv);
-}
-
-
-/* handle the SCM's ControlService() callbacks to our service */
-
-static VOID WINAPI service_nt_ctrl(DWORD dwCtrlCode)
-{
- if (dwCtrlCode == SERVICE_CONTROL_STOP)
- {
- ap_start_shutdown();
- globdat.ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
- ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 3000);
- return;
- }
- if (dwCtrlCode == SERVICE_APACHE_RESTART)
- {
- ap_start_restart(1);
- globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;
- ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000);
- return;
- }
-
- ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, NO_ERROR, 0);
-}
-
-
-long __stdcall service_stderr_thread(LPVOID hPipe)
-{
- HANDLE hPipeRead = (HANDLE) hPipe;
- HANDLE hEventSource;
- char errbuf[256];
- char *errmsg = errbuf;
- const char *errarg[9];
- DWORD errlen = 0;
- DWORD errres;
- HKEY hk;
-
- errarg[0] = "The Apache service named";
- errarg[1] = mpm_display_name;
- errarg[2] = "reported the following error:\r\n>>>";
- errarg[3] = errmsg;
- errarg[4] = "<<<\r\n before the error.log file could be opened.\r\n";
- errarg[5] = "More information may be available in the error.log file.";
- errarg[6] = NULL;
- errarg[7] = NULL;
- errarg[8] = NULL;
-
- /* What are we going to do in here, bail on the user? not. */
- if (!RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services"
- "\\EventLog\\Application\\Apache Service", &hk))
- {
- /* The stock message file */
- char *netmsgkey = "%SystemRoot%\\System32\\netmsg.dll";
- DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
- EVENTLOG_INFORMATION_TYPE;
-
- RegSetValueEx(hk, "EventMessageFile", 0, REG_EXPAND_SZ,
- (LPBYTE) netmsgkey, strlen(netmsgkey) + 1);
-
- RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD,
- (LPBYTE) &dwData, sizeof(dwData));
- RegCloseKey(hk);
- }
-
- hEventSource = RegisterEventSource(NULL, "Apache Service");
-
- while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))
- {
- if ((errmsg > errbuf) || !isspace(*errmsg))
- {
- ++errlen;
- ++errmsg;
- if ((*(errmsg - 1) == '\n') || (errlen == sizeof(errbuf) - 1))
- {
- while (errlen && isspace(errbuf[errlen - 1]))
- --errlen;
- errbuf[errlen] = '\0';
-
- /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
- * The event code in netmsg.dll is 3299
- */
- ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,
- 3299, NULL, 9, 0, errarg, NULL);
- errmsg = errbuf;
- errlen = 0;
- }
- }
- }
-
- CloseHandle(hPipeRead);
- return 0;
-}
-
-
-/* service_nt_main_fn is outside of the call stack and outside of the
- * primary server thread... so now we _really_ need a placeholder!
- * The winnt_rewrite_args has created and shared mpm_new_argv with us.
- */
-extern apr_array_header_t *mpm_new_argv;
-
-static void __stdcall service_nt_main_fn(DWORD argc, LPTSTR *argv)
-{
- HANDLE waitfor[2];
- HANDLE hCurrentProcess;
- HANDLE hPipeRead = NULL;
- HANDLE hPipeWrite = NULL;
- HANDLE hPipeReadDup;
- HANDLE thread;
- DWORD threadid;
- SECURITY_ATTRIBUTES sa = {0};
- const char *ignored;
-
- /* args and service names live in the same pool */
- mpm_service_set_name(mpm_new_argv->cont, &ignored, argv[0]);
-
- globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;
- globdat.ssStatus.dwServiceSpecificExitCode = 0;
- globdat.ssStatus.dwCheckPoint = 1;
-
- if (!(globdat.hServiceStatus = RegisterServiceCtrlHandler(argv[0], service_nt_ctrl)))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(),
- NULL, "Failure registering service handler");
- PulseEvent(globdat.signal_monitor);
- return;
- }
-
- ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, // service state
- NO_ERROR, // exit code
- 3000); // wait hint, 3 seconds more
-
- /* Create a pipe to send stderr messages to the system error log */
- hCurrentProcess = GetCurrentProcess();
- if (CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0))
- {
- if (DuplicateHandle(hCurrentProcess, hPipeRead, hCurrentProcess,
- &hPipeReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
- {
- CloseHandle(hPipeRead);
- hPipeRead = hPipeReadDup;
- thread = CreateThread(NULL, 0, service_stderr_thread,
- (LPVOID) hPipeRead, 0, &threadid);
- if (thread)
- {
- int fh;
- FILE *fl;
- CloseHandle(thread);
- fflush(stderr);
- SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);
-
- fh = _open_osfhandle((long) STD_ERROR_HANDLE,
- _O_WRONLY | _O_BINARY);
- dup2(fh, STDERR_FILENO);
- fl = _fdopen(STDERR_FILENO, "wcb");
- memcpy(stderr, fl, sizeof(FILE));
- }
- else
- {
- CloseHandle(hPipeRead);
- CloseHandle(hPipeWrite);
- hPipeWrite = NULL;
- }
- }
- else
- {
- CloseHandle(hPipeRead);
- CloseHandle(hPipeWrite);
- hPipeWrite = NULL;
- }
- }
-
- /* We need to append all the command arguments passed via StartService()
- * to our running service... which just got here via the SCM...
- * but we hvae no interest in argv[0] for the mpm_new_argv list.
- */
- if (argc > 1)
- {
- char **cmb_data;
-
- mpm_new_argv->nalloc = mpm_new_argv->nelts + argc - 1;
- cmb_data = apr_palloc(mpm_new_argv->cont,
- mpm_new_argv->nalloc * sizeof(const char *));
-
- /* mpm_new_argv remains first (of lower significance) */
- memcpy (cmb_data, mpm_new_argv->elts,
- mpm_new_argv->elt_size * mpm_new_argv->nelts);
-
- /* Service args follow from StartService() invocation */
- memcpy (cmb_data + mpm_new_argv->nelts, argv + 1,
- mpm_new_argv->elt_size * (argc - 1));
-
- /* The replacement arg list is complete */
- mpm_new_argv->elts = (char *)cmb_data;
- mpm_new_argv->nelts = mpm_new_argv->nalloc;
- }
-
- /* Let the main thread continue now... but hang on to the
- * signal_monitor event so we can take further action
- */
- SetEvent(globdat.signal_monitor);
-
- waitfor[0] = globdat.signal_monitor;
- waitfor[1] = globdat.mpm_thread;
- WaitForMultipleObjects(2, waitfor, FALSE, INFINITE);
- /* The process is ready to terminate, or already has */
-
- CloseHandle(hPipeWrite);
-}
-
-
-DWORD WINAPI service_nt_dispatch_thread(LPVOID nada)
-{
- apr_status_t rv = APR_SUCCESS;
-
- SERVICE_TABLE_ENTRY dispatchTable[] =
- {
- { "", service_nt_main_fn },
- { NULL, NULL }
- };
-
- if (!StartServiceCtrlDispatcher(dispatchTable))
- {
- /* This is a genuine failure of the SCM. */
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "Error starting service control dispatcher");
- }
-
- globdat.service_thread_id = 0;
- return (rv);
-}
-
-
-apr_status_t mpm_service_set_name(apr_pool_t *p, const char **display_name,
- const char *set_name)
-{
- char *key_name;
- apr_status_t rv;
-
- /* ### Needs improvement, on Win2K the user can _easily_
- * change the display name to a string that doesn't reflect
- * the internal service name + whitespace!
- */
- mpm_service_name = apr_palloc(p, strlen(set_name) + 1);
- apr_collapse_spaces((char*) mpm_service_name, set_name);
- key_name = apr_psprintf(p, SERVICECONFIG, mpm_service_name);
- rv = ap_registry_get_value(p, key_name, "DisplayName", &mpm_display_name);
- if (rv != APR_SUCCESS) {
- /* Take the given literal name if there is no service entry */
- mpm_display_name = apr_pstrdup(p, set_name);
- }
- *display_name = mpm_display_name;
- return rv;
-}
-
-
-apr_status_t mpm_merge_service_args(apr_pool_t *p,
- apr_array_header_t *args,
- int fixed_args)
-{
- apr_array_header_t *svc_args = NULL;
- char conf_key[MAX_PATH];
- char **cmb_data;
- apr_status_t rv;
-
- apr_snprintf(conf_key, sizeof(conf_key), SERVICEPARAMS, mpm_service_name);
- rv = ap_registry_get_array(p, conf_key, "ConfigArgs", &svc_args);
- if (rv != APR_SUCCESS) {
- if (rv == ERROR_FILE_NOT_FOUND) {
- ap_log_error(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, NULL,
- "No ConfigArgs registered for %s, perhaps "
- "this service is not installed?",
- mpm_service_name);
- return APR_SUCCESS;
- }
- else
- return (rv);
- }
-
- if (!svc_args || svc_args->nelts == 0) {
- return (APR_SUCCESS);
- }
-
- /* Now we have the mpm_service_name arg, and the mpm_runservice_nt()
- * call appended the arguments passed by StartService(), so it's
- * time to _prepend_ the default arguments for the server from
- * the service's default arguments (all others override them)...
- */
- args->nalloc = args->nelts + svc_args->nelts;
- cmb_data = apr_palloc(p, args->nalloc * sizeof(const char *));
-
- /* First three args (argv[0], -f, path) remain first */
- memcpy(cmb_data, args->elts, args->elt_size * fixed_args);
-
- /* Service args follow from service registry array */
- memcpy(cmb_data + fixed_args, svc_args->elts,
- svc_args->elt_size * svc_args->nelts);
-
- /* Remaining new args follow */
- memcpy(cmb_data + fixed_args + svc_args->nelts,
- (const char **)args->elts + fixed_args,
- args->elt_size * (args->nelts - fixed_args));
-
- args->elts = (char *)cmb_data;
- args->nelts = args->nalloc;
-
- return APR_SUCCESS;
-}
-
-
-void service_stopped(void)
-{
- /* Still have a thread & window to clean up, so signal now */
- if (globdat.service_thread_id)
- {
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- ReportStatusToSCMgr(SERVICE_STOPPED, // service state
- NO_ERROR, // exit code
- 0); // wait hint
-
- /* Cause the service_nt_main_fn to complete */
- SetEvent(globdat.signal_monitor);
- }
- else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
- {
- RegisterServiceProcess(0, 0);
- PostThreadMessage(globdat.service_thread_id, WM_CLOSE, 0, 0);
- }
-
- WaitForSingleObject(globdat.service_thread, 5000);
- CloseHandle(globdat.service_thread);
- }
-}
-
-
-apr_status_t mpm_service_to_start(const char **display_name)
-{
- HANDLE waitfor[2];
-
- globdat.mpm_thread = GetCurrentThread();
-
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- globdat.signal_monitor = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (globdat.signal_monitor)
- globdat.service_thread = CreateThread(NULL, 0,
- service_nt_dispatch_thread,
- NULL, 0,
- &globdat.service_thread_id);
- }
- else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
- {
- if (!RegisterServiceProcess(0, 1))
- return GetLastError();
-
- globdat.signal_monitor = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (globdat.signal_monitor)
- globdat.service_thread = CreateThread(NULL, 0,
- monitor_service_9x_thread,
- (LPVOID) mpm_service_name, 0,
- &globdat.service_thread_id);
- }
-
- if (globdat.signal_monitor && globdat.service_thread)
- {
- waitfor[0] = globdat.signal_monitor;
- waitfor[1] = globdat.service_thread;
-
- /* SetEvent(globdat.signal_monitor) to clean up the SCM thread */
- if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
- CloseHandle(globdat.service_thread);
- return APR_ENOTHREAD;
- }
- }
-
- if (globdat.service_thread_id)
- atexit(service_stopped);
- else if (globdat.service_thread)
- CloseHandle(globdat.service_thread);
-
- *display_name = mpm_display_name;
- return APR_SUCCESS;
-}
-
-
-apr_status_t mpm_service_started(void)
-{
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- ReportStatusToSCMgr(SERVICE_RUNNING, // service state
- NO_ERROR, // exit code
- 0); // wait hint
- }
- return APR_SUCCESS;
-}
-
-
-void mpm_service_stopping(void)
-{
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- ReportStatusToSCMgr(SERVICE_STOP_PENDING, // service state
- NO_ERROR, // exit code
- 3000); // wait hint
-}
-
-
-apr_status_t mpm_service_install(apr_pool_t *ptemp, int argc,
- const char * const * argv)
-{
- char key_name[MAX_PATH];
- char exe_path[MAX_PATH];
- char *launch_cmd;
- apr_status_t(rv);
-
- printf("Installing the %s service\n", mpm_display_name);
-
- if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0)
- {
- apr_status_t rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "GetModuleFileName failed");
- return rv;
- }
-
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- // TODO: Determine the minimum permissions required for security
- schSCManager = OpenSCManager(NULL, NULL, /* local, default database */
- SC_MANAGER_ALL_ACCESS);
- if (!schSCManager) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "Failed to open the WinNT service manager");
- return (rv);
- }
-
- launch_cmd = apr_psprintf(ptemp, "\"%s\" -k runservice", exe_path);
-
- /* RPCSS is the Remote Procedure Call (RPC) Locator required for DCOM
- * communication pipes. I am far from convinced we should add this to
- * the default service dependencies, but be warned that future apache
- * modules or ISAPI dll's may depend on it.
- */
- schService = CreateService(schSCManager, // SCManager database
- mpm_service_name, // name of service
- mpm_display_name, // name to display
- SERVICE_ALL_ACCESS, // access required
- SERVICE_WIN32_OWN_PROCESS, // service type
- SERVICE_AUTO_START, // start type
- SERVICE_ERROR_NORMAL, // error control type
- launch_cmd, // service's binary
- NULL, // no load svc group
- NULL, // no tag identifier
- "Tcpip\0Afd\0", // dependencies
- NULL, // use SYSTEM account
- NULL); // no password
-
- if (!schService)
- {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "Failed to create WinNT Service Profile");
- CloseServiceHandle(schSCManager);
- return (rv);
- }
-
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- }
- else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
- {
- /* Store the launch command in the registry */
- launch_cmd = apr_psprintf(ptemp, "\"%s\" -n %s -k runservice",
- exe_path, mpm_service_name);
- rv = ap_registry_store_value(SERVICECONFIG9X, mpm_service_name, launch_cmd);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: Failed to add the RunServices registry entry.",
- mpm_display_name);
- return (rv);
- }
-
- apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
- rv = ap_registry_store_value(key_name, "DisplayName", mpm_display_name);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: Failed to store DisplayName in the registry.",
- mpm_display_name);
- return (rv);
- }
- }
-
- /* For both WinNT & Win9x store the service ConfigArgs in the registry...
- */
- apr_snprintf(key_name, sizeof(key_name), SERVICEPARAMS, mpm_service_name);
- rv = ap_registry_store_array(ptemp, key_name, "ConfigArgs", argc, argv);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: Failed to store the ConfigArgs in the registry.",
- mpm_display_name);
- return (rv);
- }
- printf("The %s service is successfully installed.\n", mpm_display_name);
-}
-
-
-apr_status_t mpm_service_uninstall(void)
-{
- char key_name[MAX_PATH];
- apr_status_t rv;
-
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- printf("Removing the %s service\n", mpm_display_name);
-
- // TODO: Determine the minimum permissions required for security
- schSCManager = OpenSCManager(NULL, NULL, /* local, default database */
- SC_MANAGER_ALL_ACCESS);
- if (!schSCManager) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "Failed to open the WinNT service manager.");
- return (rv);
- }
-
- schService = OpenService(schSCManager, mpm_service_name, SERVICE_ALL_ACCESS);
-
- if (!schService) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: OpenService failed", mpm_display_name);
- return (rv);
- }
-
- /* assure the service is stopped before continuing
- *
- * This may be out of order... we might not be able to be
- * granted all access if the service is running anyway.
- *
- * And do we want to make it *this easy* for them
- * to uninstall their service unintentionally?
- */
- // ap_stop_service(schService);
-
- if (DeleteService(schService) == 0) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: Failed to delete the service.", mpm_display_name);
- return (rv);
- }
-
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- }
- else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
- {
- printf("Removing the %s service\n", mpm_display_name);
-
- /* TODO: assure the service is stopped before continuing */
-
- if (ap_registry_delete_value(SERVICECONFIG9X, mpm_service_name)) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: Failed to remove the RunServices registry "
- "entry.", mpm_display_name);
- return (rv);
- }
-
- /* we blast Services/us, not just the Services/us/Parameters branch */
- apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
- if (ap_registry_delete_key(key_name))
- {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: Failed to remove the service config from the "
- "registry.", mpm_display_name);
- return (rv);
- }
- }
- printf("The %s service has been removed successfully.\n", mpm_display_name);
- return APR_SUCCESS;
-}
-
-
-/* signal_service_transition is a simple thunk to signal the service
- * and monitor it's successful transition. If the signal passed is 0,
- * then the caller is assumed to already have performed some service
- * operation to be monitored (such as StartService), and no actual
- * ControlService signal is sent.
- */
-
-static int signal_service_transition(SC_HANDLE schService, DWORD signal, DWORD pending, DWORD complete)
-{
- if (signal && !ControlService(schService, signal, &globdat.ssStatus))
- return FALSE;
-
- do {
- Sleep(1000);
- if (!QueryServiceStatus(schService, &globdat.ssStatus))
- return FALSE;
- } while (globdat.ssStatus.dwCurrentState == pending);
-
- return (globdat.ssStatus.dwCurrentState == complete);
-}
-
-
-apr_status_t mpm_service_start(apr_pool_t *ptemp, int argc,
- const char * const * argv)
-{
- apr_status_t rv;
-
- printf("Starting the %s service\n", mpm_display_name);
-
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- char **start_argv;
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- // TODO: Determine the minimum permissions required for security
- schSCManager = OpenSCManager(NULL, NULL, /* local, default database */
- SC_MANAGER_ALL_ACCESS);
- if (!schSCManager) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "Failed to open the WinNT service manager");
- return (rv);
- }
-
- schService = OpenService(schSCManager, mpm_service_name,
- SERVICE_START | SERVICE_QUERY_STATUS);
- if (!schService) {
- rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "%s: Failed to open the service.", mpm_display_name);
- CloseServiceHandle(schSCManager);
- return (rv);
- }
-
- if (QueryServiceStatus(schService, &globdat.ssStatus)
- && (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING)) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL,
- "Service %s is already started!", mpm_display_name);
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- return 0;
- }
-
- argc += 1;
- start_argv = apr_palloc(ptemp, argc * sizeof(const char **));
- start_argv[0] = mpm_service_name;
- if (argc > 1)
- memcpy(start_argv + 1, argv, (argc - 1) * sizeof(const char **));
-
- rv = APR_EINIT;
- if (StartService(schService, argc, start_argv)
- && signal_service_transition(schService, 0, /* test only */
- SERVICE_START_PENDING,
- SERVICE_RUNNING))
- rv = APR_SUCCESS;
-
- if (rv != APR_SUCCESS)
- rv = apr_get_os_error();
-
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- }
- else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
- {
- STARTUPINFO si; /* Filled in prior to call to CreateProcess */
- PROCESS_INFORMATION pi; /* filled in on call to CreateProcess */
- char exe_path[MAX_PATH];
- char *pCommand;
- int i;
-
- /* Locate the active top level window named service_name
- * provided the class is ApacheWin95ServiceMonitor
- */
- if (FindWindow("ApacheWin95ServiceMonitor", mpm_service_name)) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL,
- "Service %s is already started!", mpm_display_name);
- return 0;
- }
-
- /* This may not appear intuitive, but Win9x will not allow a process
- * to detach from the console without releasing the entire console.
- * Ergo, we must spawn a new process for the service to get back our
- * console window.
- * The config is pre-flighted, so there should be no danger of failure.
- */
-
- if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0)
- {
- apr_status_t rv = apr_get_os_error();
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
- "GetModuleFileName failed");
- return rv;
- }
-
- pCommand = apr_psprintf(ptemp, "\"%s\" -n %s -k runservice",
- exe_path, mpm_service_name);
- for (i = 0; i < argc; ++i) {
- pCommand = apr_pstrcat(ptemp, pCommand,
- " \"", argv[i], "\"", NULL);
- }
-
- memset(&si, 0, sizeof(si));
- memset(&pi, 0, sizeof(pi));
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE; /* This might be redundant */
-
- rv = APR_EINIT;
- if (CreateProcess(NULL, pCommand, NULL, NULL, FALSE,
- DETACHED_PROCESS, /* Creation flags */
- NULL, NULL, &si, &pi))
- {
- DWORD code;
- while (GetExitCodeProcess(pi.hProcess, &code) == STILL_ACTIVE) {
- if (FindWindow("ApacheWin95ServiceMonitor", mpm_service_name)) {
- rv = APR_SUCCESS;
- break;
- }
- Sleep (1000);
- }
- }
-
- if (rv != APR_SUCCESS)
- rv = apr_get_os_error();
-
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- }
-
- if (rv == APR_SUCCESS)
- printf("The %s service is running.\n", mpm_display_name);
- else
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
- "%s: Failed to start the service process.",
- mpm_display_name);
-
- return rv;
-}
-
-
-/* signal is zero to stop, non-zero for restart */
-
-void mpm_signal_service(apr_pool_t *ptemp, int signal)
-{
- int success = FALSE;
-
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- schSCManager = OpenSCManager(NULL, NULL, // default machine & database
- SC_MANAGER_ALL_ACCESS);
-
- if (!schSCManager) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL,
- "Failed to open the NT Service Manager");
- return;
- }
-
- schService = OpenService(schSCManager, mpm_service_name,
- SERVICE_ALL_ACCESS);
-
- if (schService == NULL) {
- /* Could not open the service */
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL,
- "Failed to open the %s Service", mpm_display_name);
- CloseServiceHandle(schSCManager);
- return;
- }
-
- if (!QueryServiceStatus(schService, &globdat.ssStatus)) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL,
- "Query of Service %s failed", mpm_display_name);
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- return;
- }
-
- if (!signal && (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED)) {
- printf("The %s service is not started.\n", mpm_display_name);
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- return;
- }
-
- printf("The %s service is %s.\n", mpm_display_name,
- signal ? "restarting" : "stopping");
-
- if (!signal)
- success = signal_service_transition(schService,
- SERVICE_CONTROL_STOP,
- SERVICE_STOP_PENDING,
- SERVICE_STOPPED);
- else if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) {
- mpm_service_start(ptemp, 0, NULL);
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- return;
- }
- else
- success = signal_service_transition(schService,
- SERVICE_APACHE_RESTART,
- SERVICE_START_PENDING,
- SERVICE_RUNNING);
-
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- }
- else /* !isWindowsNT() */
- {
- DWORD service_pid;
- HANDLE hwnd;
- char prefix[20];
- /* Locate the active top level window named service_name
- * provided the class is ApacheWin95ServiceMonitor
- */
- hwnd = FindWindow("ApacheWin95ServiceMonitor", mpm_service_name);
- if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid))
- globdat.ssStatus.dwCurrentState = SERVICE_RUNNING;
- else
- {
- globdat.ssStatus.dwCurrentState = SERVICE_STOPPED;
- if (!signal) {
- printf("The %s service is not started.\n", mpm_display_name);
- return;
- }
- }
-
- printf("The %s service is %s.\n", mpm_display_name,
- signal ? "restarting" : "stopping");
-
- apr_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid);
- setup_signal_names(prefix);
-
- if (!signal)
- {
- int ticks = 60;
- ap_start_shutdown();
- while (--ticks)
- {
- if (!IsWindow(hwnd)) {
- success = TRUE;
- break;
- }
- Sleep(1000);
- }
- }
- else /* !stop */
- {
- /* TODO: Aught to add a little test to the restart logic, and
- * store the restart counter in the window's user dword.
- * Then we can hang on and report a successful restart. But
- * that's a project for another day.
- */
- if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) {
- mpm_service_start(ptemp, 0, NULL);
- return;
- }
- else {
- success = TRUE;
- ap_start_restart(1);
- }
- }
- }
-
- if (success)
- printf("The %s service has %s.\n", mpm_display_name,
- signal ? "restarted" : "stopped");
- else
- printf("Failed to %s the %s service.\n",
- signal ? "restart" : "stop", mpm_display_name);
-}
diff --git a/server/mpm_common.c b/server/mpm_common.c
deleted file mode 100644
index d024c24978..0000000000
--- a/server/mpm_common.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* The purpose of this file is to store the code that MOST mpm's will need
- * this does not mean a function only goes into this file if every MPM needs
- * it. It means that if a function is needed by more than one MPM, and
- * future maintenance would be served by making the code common, then the
- * function belongs here.
- *
- * This is going in src/main because it is not platform specific, it is
- * specific to multi-process servers, but NOT to Unix. Which is why it
- * does not belong in src/os/unix
- */
-
-#include "apr.h"
-#include "apr_thread_proc.h"
-#include "apr_signal.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "mpm.h"
-#include "mpm_common.h"
-#include "ap_mpm.h"
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-
-#ifdef AP_MPM_NEEDS_RECLAIM_CHILD_PROCESSES
-void ap_reclaim_child_processes(int terminate)
-{
- int i;
- long int waittime = 1024 * 16; /* in usecs */
- apr_status_t waitret;
- int tries;
- int not_dead_yet;
- int max_daemons;
-
- ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons);
- MPM_SYNC_CHILD_TABLE();
-
- for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
- /* don't want to hold up progress any more than
- * necessary, but we need to allow children a few moments to exit.
- * Set delay with an exponential backoff.
- */
- waittime = waittime * 4;
- apr_sleep(waittime);
-
- /* now see who is done */
- not_dead_yet = 0;
- for (i = 0; i < max_daemons; ++i) {
- pid_t pid = MPM_CHILD_PID(i);
- apr_proc_t proc;
-
- if (pid == 0)
- continue;
-
- proc.pid = pid;
- waitret = apr_proc_wait(&proc, APR_NOWAIT);
- if (waitret != APR_CHILD_NOTDONE) {
- MPM_NOTE_CHILD_KILLED(i);
- continue;
- }
- ++not_dead_yet;
- switch (tries) {
- case 1: /* 16ms */
- case 2: /* 82ms */
- case 3: /* 344ms */
- case 4: /* 16ms */
- break;
- case 5: /* 82ms */
- case 6: /* 344ms */
- case 7: /* 1.4sec */
- /* ok, now it's being annoying */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
- 0, ap_server_conf,
- "child process %ld still did not exit, sending a SIGTERM",
- (long)pid);
- kill(pid, SIGTERM);
- break;
- case 8: /* 6 sec */
- /* die child scum */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
- 0, ap_server_conf,
- "child process %ld still did not exit, sending a SIGKILL",
- (long)pid);
-#ifndef BEOS
- kill(pid, SIGKILL);
-#else
- /* sending a SIGKILL kills the entire team on BeOS, and as
- * httpd thread is part of that team it removes any chance
- * of ever doing a restart. To counter this I'm changing to
- * use a kinder, gentler way of killing a specific thread
- * that is just as effective.
- */
- kill_thread(pid);
-#endif
- break;
- case 9: /* 14 sec */
- /* gave it our best shot, but alas... If this really
- * is a child we are trying to kill and it really hasn't
- * exited, we will likely fail to bind to the port
- * after the restart.
- */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
- 0, ap_server_conf,
- "could not make child process %ld exit, "
- "attempting to continue anyway", (long)pid);
- break;
- }
- }
-#if APR_HAS_OTHER_CHILD
- apr_proc_other_child_check();
-#endif
- if (!not_dead_yet) {
- /* nothing left to wait for */
- break;
- }
- }
-}
-#endif /* NEED_RECLAIM_CHILD_PROCESSES */
-
-/* number of calls to wait_or_timeout between writable probes */
-#ifndef INTERVAL_OF_WRITABLE_PROBES
-#define INTERVAL_OF_WRITABLE_PROBES 10
-#endif
-static int wait_or_timeout_counter;
-
-void ap_wait_or_timeout(apr_wait_t *status, apr_proc_t *ret, apr_pool_t *p)
-{
- apr_status_t rv;
-
- ++wait_or_timeout_counter;
- if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
- wait_or_timeout_counter = 0;
-#if APR_HAS_OTHER_CHILD
- apr_proc_probe_writable_fds();
-#endif
- }
- rv = apr_proc_wait_all_procs(ret, status, APR_NOWAIT, p);
- if (APR_STATUS_IS_EINTR(rv)) {
- ret->pid = -1;
- return;
- }
- if (APR_STATUS_IS_CHILD_DONE(rv)) {
- return;
- }
-#ifdef NEED_WAITPID
- if ((ret = reap_children(status)) > 0) {
- return;
- }
-#endif
- apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL);
- ret->pid = -1;
- return;
-}
-
-void ap_process_child_status(apr_proc_t *pid, apr_wait_t status)
-{
- int signum = WTERMSIG(status);
- const char *sigdesc = apr_signal_get_description(signum);
-
- /* Child died... if it died due to a fatal error,
- * we should simply bail out.
- */
- if ((WIFEXITED(status)) &&
- WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
- ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, ap_server_conf,
- "Child %ld returned a Fatal error..." APR_EOL_STR
- "Apache is exiting!",
- (long)pid->pid);
- exit(APEXIT_CHILDFATAL);
- }
-
- if (WIFSIGNALED(status)) {
- switch (signum) {
- case SIGTERM:
- case SIGHUP:
- case SIGWINCH:
- case SIGKILL:
- break;
- default:
-#ifdef WCOREDUMP
- if (WCOREDUMP(status)) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
- 0, ap_server_conf,
- "child pid %ld exit signal %s (%d), "
- "possible coredump in %s",
- (long)pid->pid, sigdesc, signum,
- ap_coredump_dir);
- }
- else
-#endif
- {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
- 0, ap_server_conf,
- "child pid %ld exit signal %s (%d)",
- (long)pid->pid, sigdesc, signum);
- }
- }
- }
-}
-
-#if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
-void ap_sock_disable_nagle(apr_socket_t *s)
-{
- /* The Nagle algorithm says that we should delay sending partial
- * packets in hopes of getting more data. We don't want to do
- * this; we are not telnet. There are bad interactions between
- * persistent connections and Nagle's algorithm that have very severe
- * performance penalties. (Failing to disable Nagle is not much of a
- * problem with simple HTTP.)
- *
- * In spite of these problems, failure here is not a shooting offense.
- */
- apr_status_t status = apr_setsocketopt(s, APR_TCP_NODELAY, 1);
-
- if (status != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, status, ap_server_conf,
- "setsockopt: (TCP_NODELAY)");
- }
-}
-#endif
-
-AP_DECLARE(uid_t) ap_uname2id(const char *name)
-{
- struct passwd *ent;
-
- if (name[0] == '#')
- return (atoi(&name[1]));
-
- if (!(ent = getpwnam(name))) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "%s: bad user name %s", ap_server_argv0, name);
- exit(1);
- }
- return (ent->pw_uid);
-}
-
-AP_DECLARE(gid_t) ap_gname2id(const char *name)
-{
- struct group *ent;
-
- if (name[0] == '#')
- return (atoi(&name[1]));
-
- if (!(ent = getgrnam(name))) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "%s: bad group name %s", ap_server_argv0, name); exit(1);
- }
- return (ent->gr_gid);
-}
-
-#ifndef HAVE_INITGROUPS
-int initgroups(const char *name, gid_t basegid)
-{
-#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) || defined(TPF) || defined(__TANDEM) || defined(OS2) || defined(WIN32)
-/* QNX, MPE and BeOS do not appear to support supplementary groups. */
- return 0;
-#else /* ndef QNX */
- gid_t groups[NGROUPS_MAX];
- struct group *g;
- int index = 0;
-
- setgrent();
-
- groups[index++] = basegid;
-
- while (index < NGROUPS_MAX && ((g = getgrent()) != NULL))
- if (g->gr_gid != basegid) {
- char **names;
-
- for (names = g->gr_mem; *names != NULL; ++names)
- if (!strcmp(*names, name))
- groups[index++] = g->gr_gid;
- }
-
- endgrent();
-
- return setgroups(index, groups);
-#endif /* def QNX */
-}
-#endif /* def NEED_INITGROUPS */
-
-
diff --git a/server/protocol.c b/server/protocol.c
deleted file mode 100644
index 93db7c32d0..0000000000
--- a/server/protocol.c
+++ /dev/null
@@ -1,1176 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_protocol.c --- routines which directly communicate with the client.
- *
- * Code originally by Rob McCool; much redone by Robert S. Thau
- * and the Apache Software Foundation.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_buckets.h"
-#include "apr_lib.h"
-#include "apr_signal.h"
-
-#define APR_WANT_STDIO /* for sscanf */
-#define APR_WANT_STRFUNC
-#define APR_WANT_MEMFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "util_filter.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_main.h"
-#include "http_request.h"
-#include "http_vhost.h"
-#include "http_log.h" /* For errors detected in basic auth common
- * support code... */
-#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
-#include "util_charset.h"
-#include "util_ebcdic.h"
-
-#if APR_HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(post_read_request)
- APR_HOOK_LINK(log_transaction)
- APR_HOOK_LINK(http_method)
- APR_HOOK_LINK(default_port)
-)
-
-/*
- * Builds the content-type that should be sent to the client from the
- * content-type specified. The following rules are followed:
- * - if type is NULL, type is set to ap_default_type(r)
- * - if charset adding is disabled, stop processing and return type.
- * - then, if there are no parameters on type, add the default charset
- * - return type
- */
-AP_DECLARE(const char *)ap_make_content_type(request_rec *r, const char *type)
-{
- static const char *needcset[] = {
- "text/plain",
- "text/html",
- NULL };
- const char **pcset;
- core_dir_config *conf =
- (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- if (!type) {
- type = ap_default_type(r);
- }
- if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) {
- return type;
- }
-
- if (ap_strcasestr(type, "charset=") != NULL) {
- /* already has parameter, do nothing */
- /* XXX we don't check the validity */
- ;
- }
- else {
- /* see if it makes sense to add the charset. At present,
- * we only add it if the Content-type is one of needcset[]
- */
- for (pcset = needcset; *pcset ; pcset++) {
- if (ap_strcasestr(type, *pcset) != NULL) {
- type = apr_pstrcat(r->pool, type, "; charset=",
- conf->add_default_charset_name, NULL);
- break;
- }
- }
- }
- return type;
-}
-
-AP_DECLARE(void) ap_set_content_length(request_rec *r, apr_off_t clength)
-{
- r->clength = clength;
- apr_table_setn(r->headers_out, "Content-Length",
- apr_psprintf(r->pool, "%" APR_OFF_T_FMT, clength));
-}
-
-/*
- * Return the latest rational time from a request/mtime (modification time)
- * pair. We return the mtime unless it's in the future, in which case we
- * return the current time. We use the request time as a reference in order
- * to limit the number of calls to time(). We don't check for futurosity
- * unless the mtime is at least as new as the reference.
- */
-AP_DECLARE(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime)
-{
- apr_time_t now;
-
- /* For all static responses, it's almost certain that the file was
- * last modified before the beginning of the request. So there's
- * no reason to call time(NULL) again. But if the response has been
- * created on demand, then it might be newer than the time the request
- * started. In this event we really have to call time(NULL) again
- * so that we can give the clients the most accurate Last-Modified. If we
- * were given a time in the future, we return the current time - the
- * Last-Modified can't be in the future.
- */
- now = (mtime < r->request_time) ? r->request_time : apr_time_now();
- return (mtime > now) ? now : mtime;
-}
-
-/* Get a line of protocol input, including any continuation lines
- * caused by MIME folding (or broken clients) if fold != 0, and place it
- * in the buffer s, of size n bytes, without the ending newline.
- *
- * Returns -1 on error, or the length of s.
- *
- * Notes: Because the buffer uses 1 char for NUL, the most we can return is
- * (n - 1) actual characters.
- *
- * If no LF is detected on the last line due to a dropped connection
- * or a full buffer, that's considered an error.
- */
-AP_CORE_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold)
-{
- char *pos = s;
- char *last_char;
- char *beyond_buff = s + n;
- const char *temp;
- int retval;
- int total = 0;
- int looking_ahead = 0;
- apr_size_t zero = 0;
- apr_size_t length;
- conn_rec *c = r->connection;
- core_request_config *req_cfg;
- apr_bucket_brigade *b;
- apr_bucket *e;
-
- req_cfg = (core_request_config *)
- ap_get_module_config(r->request_config, &core_module);
- b = req_cfg->bb;
- /* make sure it's empty unless we're folding */
- AP_DEBUG_ASSERT(fold || APR_BRIGADE_EMPTY(b));
-
- while (1) {
- if (APR_BRIGADE_EMPTY(b)) {
- if ((retval = ap_get_brigade(c->input_filters, b, AP_MODE_BLOCKING, &zero)) != APR_SUCCESS ||
- APR_BRIGADE_EMPTY(b)) {
- apr_brigade_destroy(b);
- return -1;
- }
- }
- e = APR_BRIGADE_FIRST(b);
- if (e->length == 0) {
- apr_bucket_delete(e);
- continue;
- }
- retval = apr_bucket_read(e, &temp, &length, APR_BLOCK_READ);
- if (retval != APR_SUCCESS) {
- apr_brigade_destroy(b);
- ap_log_rerror(APLOG_MARK, APLOG_ERR, retval, r, "apr_bucket_read() failed");
- if (total) {
- break; /* report previously-read data to caller, do ap_xlate_proto_to_ascii() */
- }
- else {
- return -1;
- }
- }
-
- if ((looking_ahead) && (*temp != APR_ASCII_BLANK) && (*temp != APR_ASCII_TAB)) {
- /* can't fold because next line isn't indented,
- * so return what we have. lookahead brigade is
- * stashed on req_cfg->bb
- */
- AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(req_cfg->bb));
- break;
- }
- last_char = pos + length - 1;
- if (last_char < beyond_buff) {
- memcpy(pos, temp, length);
- apr_bucket_delete(e);
- }
- else {
- /* input line was larger than the caller's buffer */
- apr_brigade_destroy(b);
-
- /* don't need to worry about req_cfg->bb being bogus.
- * the request is about to die, and ErrorDocument
- * redirects get a new req_cfg->bb
- */
-
- return -1;
- }
-
- pos = last_char; /* Point at the last character */
-
- if (*pos == APR_ASCII_LF) { /* Did we get a full line of input? */
-
- if (pos > s && *(pos - 1) == APR_ASCII_CR) {
- --pos; /* zap optional CR before LF */
- }
-
- /*
- * Trim any extra trailing spaces or tabs except for the first
- * space or tab at the beginning of a blank string. This makes
- * it much easier to check field values for exact matches, and
- * saves memory as well. Terminate string at end of line.
- */
- while (pos > (s + 1) &&
- (*(pos - 1) == APR_ASCII_BLANK || *(pos - 1) == APR_ASCII_TAB)) {
- --pos; /* trim extra trailing spaces or tabs */
- }
- *pos = '\0'; /* zap end of string */
- total = pos - s; /* update total string length */
-
- /* look ahead another line if line folding is desired
- * and this line isn't empty
- */
- if (fold && total) {
- looking_ahead = 1;
- }
- else {
- AP_DEBUG_ASSERT(APR_BRIGADE_EMPTY(req_cfg->bb));
- break;
- }
- }
- else {
- /* no LF yet...character mode client (telnet)...keep going
- * bump past last character read,
- * and set total in case we bail before finding a LF
- */
- total = ++pos - s;
- looking_ahead = 0; /* only appropriate right after LF */
- }
- }
- ap_xlate_proto_from_ascii(s, total);
- return total;
-}
-
-/* parse_uri: break apart the uri
- * Side Effects:
- * - sets r->args to rest after '?' (or NULL if no '?')
- * - sets r->uri to request uri (without r->args part)
- * - sets r->hostname (if not set already) from request (scheme://host:port)
- */
-AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri)
-{
- int status = HTTP_OK;
-
- r->unparsed_uri = apr_pstrdup(r->pool, uri);
-
- if (r->method_number == M_CONNECT) {
- status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
- }
- else {
- /* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
- status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
- }
-
- if (ap_is_HTTP_SUCCESS(status)) {
- /* if it has a scheme we may need to do absoluteURI vhost stuff */
- if (r->parsed_uri.scheme
- && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
- r->hostname = r->parsed_uri.hostname;
- }
- else if (r->method_number == M_CONNECT) {
- r->hostname = r->parsed_uri.hostname;
- }
- r->args = r->parsed_uri.query;
- r->uri = r->parsed_uri.path ? r->parsed_uri.path
- : apr_pstrdup(r->pool, "/");
-#if defined(OS2) || defined(WIN32)
- /* Handle path translations for OS/2 and plug security hole.
- * This will prevent "http://www.wherever.com/..\..\/" from
- * returning a directory for the root drive.
- */
- {
- char *x;
-
- for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
- *x = '/';
- }
-#endif /* OS2 || WIN32 */
- }
- else {
- r->args = NULL;
- r->hostname = NULL;
- r->status = status; /* set error status */
- r->uri = apr_pstrdup(r->pool, uri);
- }
-}
-
-static int read_request_line(request_rec *r)
-{
- char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */
- const char *ll = l;
- const char *uri;
- const char *pro;
-
-#if 0
- conn_rec *conn = r->connection;
-#endif
- int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */
- int len;
-
- /* Read past empty lines until we get a real request line,
- * a read error, the connection closes (EOF), or we timeout.
- *
- * We skip empty lines because browsers have to tack a CRLF on to the end
- * of POSTs to support old CERN webservers. But note that we may not
- * have flushed any previous response completely to the client yet.
- * We delay the flush as long as possible so that we can improve
- * performance for clients that are pipelining requests. If a request
- * is pipelined then we won't block during the (implicit) read() below.
- * If the requests aren't pipelined, then the client is still waiting
- * for the final buffer flush from us, and we will block in the implicit
- * read(). B_SAFEREAD ensures that the BUFF layer flushes if it will
- * have to block during a read.
- */
-
- while ((len = ap_getline(l, sizeof(l), r, 0)) <= 0) {
- if (len < 0) { /* includes EOF */
- /* this is a hack to make sure that request time is set,
- * it's not perfect, but it's better than nothing
- */
- r->request_time = apr_time_now();
- return 0;
- }
- }
- /* we've probably got something to do, ignore graceful restart requests */
-
- /* XXX - sigwait doesn't work if the signal has been SIG_IGNed (under
- * linux 2.0 w/ glibc 2.0, anyway), and this step isn't necessary when
- * we're running a sigwait thread anyway. If/when unthreaded mode is
- * put back in, we should make sure to ignore this signal iff a sigwait
- * thread isn't used. - mvsk
-
-#ifdef SIGWINCH
- apr_signal(SIGWINCH, SIG_IGN);
-#endif
- */
-
- r->request_time = apr_time_now();
- r->the_request = apr_pstrdup(r->pool, l);
- r->method = ap_getword_white(r->pool, &ll);
-
-#if 0
-/* XXX If we want to keep track of the Method, the protocol module should do
- * it. That support isn't in the scoreboard yet. Hopefully next week
- * sometime. rbb */
- ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method", r->method);
-#endif
- uri = ap_getword_white(r->pool, &ll);
-
- /* Provide quick information about the request method as soon as known */
-
- r->method_number = ap_method_number_of(r->method);
- if (r->method_number == M_GET && r->method[0] == 'H') {
- r->header_only = 1;
- }
-
- ap_parse_uri(r, uri);
-
- /* ap_getline returns (size of max buffer - 1) if it fills up the
- * buffer before finding the end-of-line. This is only going to
- * happen if it exceeds the configured limit for a request-line.
- */
- if (len > r->server->limit_req_line) {
- r->status = HTTP_REQUEST_URI_TOO_LARGE;
- r->proto_num = HTTP_VERSION(1,0);
- r->protocol = apr_pstrdup(r->pool, "HTTP/1.0");
- return 0;
- }
-
- if (ll[0]) {
- r->assbackwards = 0;
- pro = ll;
- len = strlen(ll);
- } else {
- r->assbackwards = 1;
- pro = "HTTP/0.9";
- len = 8;
- }
- r->protocol = apr_pstrndup(r->pool, pro, len);
-
- /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */
-
- /* Avoid sscanf in the common case */
- if (len == 8 &&
- pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P' &&
- pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.' &&
- apr_isdigit(pro[7])) {
- r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0');
- } else if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor)
- && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */
- r->proto_num = HTTP_VERSION(major, minor);
- else
- r->proto_num = HTTP_VERSION(1,0);
-
- return 1;
-}
-
-static void get_mime_headers(request_rec *r)
-{
- char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* getline's two extra */
- char *value;
- char *copy;
- int len;
- int fields_read = 0;
- apr_table_t *tmp_headers;
-
- /* We'll use apr_table_overlap later to merge these into r->headers_in. */
- tmp_headers = apr_table_make(r->pool, 50);
-
- /*
- * Read header lines until we get the empty separator line, a read error,
- * the connection closes (EOF), reach the server limit, or we timeout.
- */
- while ((len = ap_getline(field, sizeof(field), r, 1)) > 0) {
-
- if (r->server->limit_req_fields &&
- (++fields_read > r->server->limit_req_fields)) {
- r->status = HTTP_BAD_REQUEST;
- apr_table_setn(r->notes, "error-notes",
- "The number of request header fields exceeds "
- "this server's limit.<P>\n");
- return;
- }
- /* ap_getline returns (size of max buffer - 1) if it fills up the
- * buffer before finding the end-of-line. This is only going to
- * happen if it exceeds the configured limit for a field size.
- */
- if (len > r->server->limit_req_fieldsize) {
- r->status = HTTP_BAD_REQUEST;
- apr_table_setn(r->notes, "error-notes",
- apr_pstrcat(r->pool,
- "Size of a request header field "
- "exceeds server limit.<P>\n"
- "<PRE>\n",
- ap_escape_html(r->pool, field),
- "</PRE>\n", NULL));
- return;
- }
- copy = apr_palloc(r->pool, len + 1);
- memcpy(copy, field, len + 1);
-
- if (!(value = strchr(copy, ':'))) { /* Find the colon separator */
- r->status = HTTP_BAD_REQUEST; /* or abort the bad request */
- apr_table_setn(r->notes, "error-notes",
- apr_pstrcat(r->pool,
- "Request header field is missing "
- "colon separator.<P>\n"
- "<PRE>\n",
- ap_escape_html(r->pool, copy),
- "</PRE>\n", NULL));
- return;
- }
-
- *value = '\0';
- ++value;
- while (*value == ' ' || *value == '\t') {
- ++value; /* Skip to start of value */
- }
-
- apr_table_addn(tmp_headers, copy, value);
- }
-
- apr_table_overlap(r->headers_in, tmp_headers, APR_OVERLAP_TABLES_MERGE);
-}
-
-request_rec *ap_read_request(conn_rec *conn)
-{
- request_rec *r;
- apr_pool_t *p;
- const char *expect;
- int access_status, keptalive;
-
- apr_pool_create(&p, conn->pool);
- r = apr_pcalloc(p, sizeof(request_rec));
- r->pool = p;
- r->connection = conn;
- r->server = conn->base_server;
-
- keptalive = conn->keepalive == 1;
- conn->keepalive = 0;
-
- r->user = NULL;
- r->ap_auth_type = NULL;
-
- r->allowed_methods = ap_make_method_list(p, 2);
-
- r->headers_in = apr_table_make(r->pool, 50);
- r->subprocess_env = apr_table_make(r->pool, 50);
- r->headers_out = apr_table_make(r->pool, 12);
- r->err_headers_out = apr_table_make(r->pool, 5);
- r->notes = apr_table_make(r->pool, 5);
-
- r->request_config = ap_create_request_config(r->pool);
- ap_run_create_request(r);
- r->per_dir_config = r->server->lookup_defaults;
-
- r->sent_bodyct = 0; /* bytect isn't for body */
-
- r->read_length = 0;
- r->read_body = REQUEST_NO_BODY;
-
- r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */
- r->the_request = NULL;
- r->output_filters = conn->output_filters;
- r->input_filters = conn->input_filters;
-
- apr_setsocketopt(conn->client_socket, APR_SO_TIMEOUT,
- (int)(keptalive
- ? r->server->keep_alive_timeout * APR_USEC_PER_SEC
- : r->server->timeout * APR_USEC_PER_SEC));
-
- ap_add_output_filter("BYTERANGE", NULL, r, r->connection);
- ap_add_output_filter("CONTENT_LENGTH", NULL, r, r->connection);
- ap_add_output_filter("HTTP_HEADER", NULL, r, r->connection);
-
- /* Get the request... */
- if (!read_request_line(r)) {
- if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "request failed: URI too long");
- ap_send_error_response(r, 0);
- ap_run_log_transaction(r);
- return r;
- }
- return NULL;
- }
- if (keptalive) {
- apr_setsocketopt(r->connection->client_socket, APR_SO_TIMEOUT,
- (int)(r->server->timeout * APR_USEC_PER_SEC));
- }
- if (!r->assbackwards) {
- get_mime_headers(r);
- if (r->status != HTTP_REQUEST_TIME_OUT) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "request failed: error reading the headers");
- ap_send_error_response(r, 0);
- ap_run_log_transaction(r);
- return r;
- }
- }
- else {
- if (r->header_only) {
- /*
- * Client asked for headers only with HTTP/0.9, which doesn't send
- * headers! Have to dink things just to make sure the error message
- * comes through...
- */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "client sent invalid HTTP/0.9 request: HEAD %s",
- r->uri);
- r->header_only = 0;
- r->status = HTTP_BAD_REQUEST;
- ap_send_error_response(r, 0);
- ap_run_log_transaction(r);
- return r;
- }
- }
-
- r->status = HTTP_OK; /* Until further notice. */
-
- /* update what we think the virtual host is based on the headers we've
- * now read. may update status.
- */
- ap_update_vhost_from_headers(r);
-
- /* we may have switched to another server */
- r->per_dir_config = r->server->lookup_defaults;
-
- if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) ||
- ((r->proto_num == HTTP_VERSION(1,1)) &&
- !apr_table_get(r->headers_in, "Host"))) {
- /*
- * Client sent us an HTTP/1.1 or later request without telling us the
- * hostname, either with a full URL or a Host: header. We therefore
- * need to (as per the 1.1 spec) send an error. As a special case,
- * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain
- * a Host: header, and the server MUST respond with 400 if it doesn't.
- */
- r->status = HTTP_BAD_REQUEST;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "client sent HTTP/1.1 request without hostname "
- "(see RFC2616 section 14.23): %s", r->uri);
- }
- if (r->status != HTTP_OK) {
- ap_send_error_response(r, 0);
- ap_run_log_transaction(r);
- return r;
- }
- if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL) &&
- (expect[0] != '\0')) {
- /*
- * The Expect header field was added to HTTP/1.1 after RFC 2068
- * as a means to signal when a 100 response is desired and,
- * unfortunately, to signal a poor man's mandatory extension that
- * the server must understand or return 417 Expectation Failed.
- */
- if (strcasecmp(expect, "100-continue") == 0) {
- r->expecting_100 = 1;
- }
- else {
- r->status = HTTP_EXPECTATION_FAILED;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
- "client sent an unrecognized expectation value of "
- "Expect: %s", expect);
- ap_send_error_response(r, 0);
- (void) ap_discard_request_body(r);
- ap_run_log_transaction(r);
- return r;
- }
- }
-
- if ((access_status = ap_run_post_read_request(r))) {
- ap_die(access_status, r);
- ap_run_log_transaction(r);
- return NULL;
- }
-
- return r;
-}
-
-/*
- * A couple of other functions which initialize some of the fields of
- * a request structure, as appropriate for adjuncts of one kind or another
- * to a request in progress. Best here, rather than elsewhere, since
- * *someone* has to set the protocol-specific fields...
- */
-
-void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
-{
- rnew->the_request = r->the_request; /* Keep original request-line */
-
- rnew->assbackwards = 1; /* Don't send headers from this. */
- rnew->no_local_copy = 1; /* Don't try to send HTTP_NOT_MODIFIED for a
- * fragment. */
- rnew->method = "GET";
- rnew->method_number = M_GET;
- rnew->protocol = "INCLUDED";
-
- rnew->status = HTTP_OK;
-
- rnew->headers_in = r->headers_in;
- rnew->subprocess_env = apr_table_copy(rnew->pool, r->subprocess_env);
- rnew->headers_out = apr_table_make(rnew->pool, 5);
- rnew->err_headers_out = apr_table_make(rnew->pool, 5);
- rnew->notes = apr_table_make(rnew->pool, 5);
-
- rnew->expecting_100 = r->expecting_100;
- rnew->read_length = r->read_length;
- rnew->read_body = REQUEST_NO_BODY;
-
- rnew->main = (request_rec *) r;
-}
-
-static void end_output_stream(request_rec *r)
-{
- apr_bucket_brigade *bb;
- apr_bucket *b;
-
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
-}
-
-void ap_finalize_sub_req_protocol(request_rec *sub)
-{
- end_output_stream(sub);
-}
-
-/* finalize_request_protocol is called at completion of sending the
- * response. Its sole purpose is to send the terminating protocol
- * information for any wrappers around the response message body
- * (i.e., transfer encodings). It should have been named finalize_response.
- */
-AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r)
-{
- while (r->next) {
- r = r->next;
- }
- /* tell the filter chain there is no more content coming */
- if (!r->eos_sent) {
- end_output_stream(r);
- }
-}
-
-/*
- * Support for the Basic authentication protocol, and a bit for Digest.
- */
-
-AP_DECLARE(void) ap_note_auth_failure(request_rec *r)
-{
- if (!strcasecmp(ap_auth_type(r), "Basic"))
- ap_note_basic_auth_failure(r);
- else if (!strcasecmp(ap_auth_type(r), "Digest"))
- ap_note_digest_auth_failure(r);
-}
-
-AP_DECLARE(void) ap_note_basic_auth_failure(request_rec *r)
-{
- if (strcasecmp(ap_auth_type(r), "Basic"))
- ap_note_auth_failure(r);
- else
- apr_table_setn(r->err_headers_out,
- (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" : "WWW-Authenticate",
- apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), "\"",
- NULL));
-}
-
-AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r)
-{
- apr_table_setn(r->err_headers_out,
- (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" : "WWW-Authenticate",
- apr_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%llx\"",
- ap_auth_name(r), r->request_time));
-}
-
-AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
-{
- const char *auth_line = apr_table_get(r->headers_in,
- (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization"
- : "Authorization");
- const char *t;
-
- if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic"))
- return DECLINED;
-
- if (!ap_auth_name(r)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
- 0, r, "need AuthName: %s", r->uri);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (!auth_line) {
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
-
- if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
- /* Client tried to authenticate using wrong auth scheme */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "client used wrong authentication scheme: %s", r->uri);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
-
- while (*auth_line== ' ' || *auth_line== '\t') {
- auth_line++;
- }
-
- t = ap_pbase64decode(r->pool, auth_line);
- /* Note that this allocation has to be made from r->connection->pool
- * because it has the lifetime of the connection. The other allocations
- * are temporary and can be tossed away any time.
- */
- r->user = ap_getword_nulls (r->pool, &t, ':');
- r->ap_auth_type = "Basic";
-
- *pw = t;
-
- return OK;
-}
-
-struct content_length_ctx {
- apr_bucket_brigade *saved;
- int compute_len;
- apr_size_t curr_len;
-};
-
-/* This filter computes the content length, but it also computes the number
- * of bytes sent to the client. This means that this filter will always run
- * through all of the buckets in all brigades
- */
-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter(ap_filter_t *f,
- apr_bucket_brigade *b)
-{
- request_rec *r = f->r;
- struct content_length_ctx *ctx;
- apr_status_t rv;
- apr_bucket *e;
- int send_it = 0;
-
- ctx = f->ctx;
- if (!ctx) { /* first time through */
- f->ctx = ctx = apr_pcalloc(r->pool, sizeof(struct content_length_ctx));
- }
-
- APR_BRIGADE_FOREACH(e, b) {
- const char *ignored;
- apr_size_t length;
-
- if (APR_BUCKET_IS_EOS(e) || APR_BUCKET_IS_FLUSH(e)) {
- send_it = 1;
- }
- if (e->length == -1) { /* if length unknown */
- rv = apr_bucket_read(e, &ignored, &length, APR_BLOCK_READ);
- if (rv != APR_SUCCESS) {
- return rv;
- }
- }
- else {
- length = e->length;
- }
- ctx->curr_len += length;
- r->bytes_sent += length;
- }
-
- if ((ctx->curr_len < AP_MIN_BYTES_TO_WRITE) && !send_it) {
- return ap_save_brigade(f, &ctx->saved, &b);
- }
-
- /* We will compute a content length if:
- * The protocol is < 1.1
- * and We can not chunk
- * and this is a keepalive request.
- * or We already have all the data
- * This is a bit confusing, because we will always buffer up
- * to AP_MIN_BYTES_TO_WRITE, so if we get all the data while
- * we are buffering that much data, we set the c-l.
- */
- if ((r->proto_num < HTTP_VERSION(1,1)
- && (!ap_find_last_token(f->r->pool,
- apr_table_get(r->headers_out,
- "Transfer-Encoding"),
- "chunked")
- && (f->r->connection->keepalive)))
- || (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(b)))) {
- ctx->compute_len = 1;
- }
- else {
- ctx->compute_len = 0;
- }
-
- if (ctx->compute_len) {
- /* save the brigade; we can't pass any data to the next
- * filter until we have the entire content length
- */
- if (!send_it) {
- ap_save_brigade(f, &ctx->saved, &b);
- return APR_SUCCESS;
- }
- ap_set_content_length(r, r->bytes_sent);
- }
- if (ctx->saved) {
- APR_BRIGADE_CONCAT(ctx->saved, b);
- apr_brigade_destroy(b);
- b = ctx->saved;
- ctx->saved = NULL;
- }
-
- ctx->curr_len = 0;
- return ap_pass_brigade(f->next, b);
-}
-
-/*
- * Send the body of a response to the client.
- */
-AP_DECLARE(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset,
- apr_size_t len, apr_size_t *nbytes)
-{
- apr_bucket_brigade *bb = NULL;
- apr_bucket *b;
- apr_status_t rv;
-
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_file_create(fd, offset, len);
- APR_BRIGADE_INSERT_TAIL(bb, b);
-
- rv = ap_pass_brigade(r->output_filters, bb);
- if (rv != APR_SUCCESS) {
- *nbytes = 0; /* no way to tell how many were actually sent */
- }
- else {
- *nbytes = len;
- }
-
- return rv;
-}
-
-#if APR_HAS_MMAP
-/* send data from an in-memory buffer */
-AP_DECLARE(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,
- size_t length)
-{
- apr_bucket_brigade *bb = NULL;
- apr_bucket *b;
-
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_mmap_create(mm, offset, length);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
-
- return mm->size; /* XXX - change API to report apr_status_t? */
-}
-#endif /* APR_HAS_MMAP */
-
-typedef struct {
- apr_bucket_brigade *bb;
-} old_write_filter_ctx;
-
-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
- ap_filter_t *f, apr_bucket_brigade *bb)
-{
- old_write_filter_ctx *ctx = f->ctx;
-
- AP_DEBUG_ASSERT(ctx);
-
- if (ctx->bb != 0) {
- /* whatever is coming down the pipe (we don't care), we
- * can simply insert our buffered data at the front and
- * pass the whole bundle down the chain.
- */
- APR_BRIGADE_CONCAT(ctx->bb, bb);
- }
-
- return ap_pass_brigade(f->next, ctx->bb);
-}
-
-static apr_status_t buffer_output(request_rec *r,
- const char *str, apr_size_t len)
-{
- ap_filter_t *f;
- old_write_filter_ctx *ctx;
-
- if (len == 0)
- return APR_SUCCESS;
-
- /* future optimization: record some flags in the request_rec to
- * say whether we've added our filter, and whether it is first.
- */
-
- /* this will typically exit on the first test */
- for (f = r->output_filters; f != NULL; f = f->next)
- if (strcmp("OLD_WRITE", f->frec->name) == 0)
- break;
- if (f == NULL) {
- /* our filter hasn't been added yet */
- ctx = apr_pcalloc(r->pool, sizeof(*ctx));
- ap_add_output_filter("OLD_WRITE", ctx, r, r->connection);
- f = r->output_filters;
- }
-
- /* if the first filter is not our buffering filter, then we have to
- * deliver the content through the normal filter chain */
- if (f != r->output_filters) {
- apr_bucket_brigade *bb = apr_brigade_create(r->pool);
- apr_bucket *b = apr_bucket_transient_create(str, len);
- APR_BRIGADE_INSERT_TAIL(bb, b);
-
- return ap_pass_brigade(r->output_filters, bb);
- }
-
- /* grab the context from our filter */
- ctx = r->output_filters->ctx;
-
- if (ctx->bb == NULL) {
- ctx->bb = apr_brigade_create(r->pool);
- }
-
- ap_fwrite(f->next, ctx->bb, str, len);
-
- return APR_SUCCESS;
-}
-
-AP_DECLARE(int) ap_rputc(int c, request_rec *r)
-{
- char c2 = (char)c;
-
- if (r->connection->aborted) {
- return -1;
- }
-
- if (buffer_output(r, &c2, 1) != APR_SUCCESS)
- return -1;
-
- return c;
-}
-
-AP_DECLARE(int) ap_rputs(const char *str, request_rec *r)
-{
- apr_size_t len;
-
- if (r->connection->aborted)
- return -1;
-
- if (buffer_output(r, str, len = strlen(str)) != APR_SUCCESS)
- return -1;
-
- return len;
-}
-
-AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
-{
- if (r->connection->aborted)
- return -1;
-
- if (buffer_output(r, buf, nbyte) != APR_SUCCESS)
- return -1;
-
- return nbyte;
-}
-
-AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va)
-{
- char buf[4096];
- apr_size_t written;
-
- if (r->connection->aborted)
- return -1;
-
- /* ### fix this mechanism to allow more than 4K of output */
- written = apr_vsnprintf(buf, sizeof(buf), fmt, va);
- if (buffer_output(r, buf, written) != APR_SUCCESS)
- return -1;
-
- return written;
-}
-
-AP_DECLARE_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt, ...)
-{
- va_list va;
- int n;
-
- if (r->connection->aborted)
- return -1;
-
- va_start(va, fmt);
- n = ap_vrprintf(r, fmt, va);
- va_end(va);
-
- return n;
-}
-
-AP_DECLARE_NONSTD(int) ap_rvputs(request_rec *r, ...)
-{
- va_list va;
- const char *s;
- apr_size_t len;
- apr_size_t written = 0;
-
- if (r->connection->aborted)
- return -1;
-
- /* ### TODO: if the total output is large, put all the strings
- ### into a single brigade, rather than flushing each time we
- ### fill the buffer */
- va_start(va, r);
- while (1) {
- s = va_arg(va, const char *);
- if (s == NULL)
- break;
-
- len = strlen(s);
- if (buffer_output(r, s, len) != APR_SUCCESS) {
- return -1;
- }
-
- written += len;
- }
- va_end(va);
-
- return written;
-}
-
-AP_DECLARE(int) ap_rflush(request_rec *r)
-{
- apr_bucket_brigade *bb;
- apr_bucket *b;
-
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS)
- return -1;
- return 0;
-}
-
-/*
- * This function sets the Last-Modified output header field to the value
- * of the mtime field in the request structure - rationalized to keep it from
- * being in the future.
- */
-AP_DECLARE(void) ap_set_last_modified(request_rec *r)
-{
- apr_time_t mod_time = ap_rationalize_mtime(r, r->mtime);
- char *datestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
- apr_rfc822_date(datestr, mod_time);
- apr_table_setn(r->headers_out, "Last-Modified", datestr);
-}
-
-AP_IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,
- (request_rec *r),(r),OK,DECLINED)
-AP_IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,
- (request_rec *r),(r),OK,DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,http_method,
- (const request_rec *r),(r),NULL)
-AP_IMPLEMENT_HOOK_RUN_FIRST(unsigned short,default_port,
- (const request_rec *r),(r),0)
diff --git a/server/request.c b/server/request.c
deleted file mode 100644
index b015def039..0000000000
--- a/server/request.c
+++ /dev/null
@@ -1,1133 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_request.c: functions to get and process requests
- *
- * Rob McCool 3/21/93
- *
- * Thoroughly revamped by rst for Apache. NB this file reads
- * best from the bottom up.
- *
- */
-
-#include "apr_strings.h"
-#include "apr_file_io.h"
-#include "apr_fnmatch.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_filter.h"
-#include "util_charset.h"
-
-#include "mod_core.h"
-
-#if APR_HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(translate_name)
- APR_HOOK_LINK(check_user_id)
- APR_HOOK_LINK(fixups)
- APR_HOOK_LINK(type_checker)
- APR_HOOK_LINK(access_checker)
- APR_HOOK_LINK(auth_checker)
- APR_HOOK_LINK(insert_filter)
- APR_HOOK_LINK(create_request)
-)
-
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name,
- (request_rec *r),(r),DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,check_user_id,
- (request_rec *r),(r),DECLINED)
-AP_IMPLEMENT_HOOK_RUN_ALL(int,fixups,
- (request_rec *r),(r),OK,DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,type_checker,
- (request_rec *r),(r),DECLINED)
-AP_IMPLEMENT_HOOK_RUN_ALL(int,access_checker,
- (request_rec *r),(r),OK,DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,auth_checker,
- (request_rec *r),(r),DECLINED)
-AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r))
-AP_IMPLEMENT_HOOK_RUN_ALL(int,create_request,(request_rec *r),(r),OK,DECLINED)
-
-/*****************************************************************
- *
- * Getting and checking directory configuration. Also checks the
- * FollowSymlinks and FollowSymOwner stuff, since this is really the
- * only place that can happen (barring a new mid_dir_walk callout).
- *
- * We can't do it as an access_checker module function which gets
- * called with the final per_dir_config, since we could have a directory
- * with FollowSymLinks disabled, which contains a symlink to another
- * with a .htaccess file which turns FollowSymLinks back on --- and
- * access in such a case must be denied. So, whatever it is that
- * checks FollowSymLinks needs to know the state of the options as
- * they change, all the way down.
- */
-
-/*
- * We don't want people able to serve up pipes, or unix sockets, or other
- * scary things. Note that symlink tests are performed later.
- */
-static int check_safe_file(request_rec *r)
-{
-
- if (r->finfo.filetype == 0 /* doesn't exist */
- || r->finfo.filetype == APR_DIR
- || r->finfo.filetype == APR_REG
- || r->finfo.filetype == APR_LNK) {
- return OK;
- }
-
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "object is not a file, directory or symlink: %s",
- r->filename);
- return HTTP_FORBIDDEN;
-}
-
-
-static int check_symlinks(char *d, int opts, apr_pool_t *p)
-{
-#if defined(OS2)
- /* OS/2 doesn't have symlinks */
- return OK;
-#else
- apr_finfo_t lfi, fi;
- char *lastp;
- int res;
-
- if (opts & OPT_SYM_LINKS)
- return OK;
-
- /*
- * Strip trailing '/', if any, off what we're checking; trailing slashes
- * make some systems follow symlinks to directories even in lstat().
- * After we've done the lstat, put it back. Also, don't bother checking
- * '/' at all...
- *
- * Note that we don't have to worry about multiple slashes here because of
- * no2slash() below...
- */
-
- lastp = d + strlen(d) - 1;
- if (lastp == d)
- return OK; /* Root directory, '/' */
-
- if (*lastp == '/')
- *lastp = '\0';
- else
- lastp = NULL;
-
- res = apr_lstat(&lfi, d, APR_FINFO_TYPE | APR_FINFO_OWNER, p);
-
- if (lastp)
- *lastp = '/';
-
- /*
- * Note that we don't reject accesses to nonexistent files (multiviews or
- * the like may cons up a way to run the transaction anyway)...
- */
-
- if ((res != APR_SUCCESS && res != APR_INCOMPLETE)
- || (lfi.filetype != APR_LNK))
- return OK;
-
- /* OK, it's a symlink. May still be OK with OPT_SYM_OWNER */
-
- if (!(opts & OPT_SYM_OWNER))
- return HTTP_FORBIDDEN;
-
- /* OPT_SYM_OWNER only works if we can get the owner from the file */
-
- if (res != APR_SUCCESS)
- return HTTP_FORBIDDEN;
-
- if (apr_stat(&fi, d, APR_FINFO_OWNER, p) != APR_SUCCESS)
- return HTTP_FORBIDDEN;
-
- /* TODO: replace with an apr_compare_users() fn */
- return (fi.user == lfi.user) ? OK : HTTP_FORBIDDEN;
-
-#endif
-}
-
-/* Dealing with the file system to get PATH_INFO
- */
-static int get_path_info(request_rec *r)
-{
- char *cp;
- char *path = r->filename;
- char *end = &path[strlen(path)];
- char *last_cp = NULL;
- int rv;
-#if defined(HAVE_DRIVE_LETTERS) || defined(HAVE_UNC_PATHS)
- char bStripSlash=1;
-#endif
-
- if (r->finfo.filetype) {
- /* assume path_info already set */
- return OK;
- }
-
-#ifdef HAVE_DRIVE_LETTERS
- /* If the directory is x:\, then we don't want to strip
- * the trailing slash since x: is not a valid directory.
- */
- if (strlen(path) == 3 && path[1] == ':' && path[2] == '/')
- bStripSlash = 0;
-#endif
-
-#ifdef HAVE_UNC_PATHS
- /* If UNC name == //machine/share/, do not
- * advance over the trailing slash. Any other
- * UNC name is OK to strip the slash.
- */
- cp = end;
- if (path[0] == '/' && path[1] == '/' &&
- path[2] != '/' && cp[-1] == '/') {
- char *p;
- int iCount=0;
- p = path;
- while ((p = strchr(p,'/')) != NULL) {
- p++;
- iCount++;
- }
-
- if (iCount == 4)
- bStripSlash = 0;
- }
-#endif
-
-#if defined(HAVE_DRIVE_LETTERS) || defined(HAVE_UNC_PATHS)
- if (bStripSlash)
-#endif
- /* Advance over trailing slashes ... NOT part of filename
- * if file is not a UNC name (Win32 only).
- */
- for (cp = end; cp > path && cp[-1] == '/'; --cp)
- continue;
-
- while (cp > path) {
-
- /* See if the pathname ending here exists... */
- *cp = '\0';
-
- /* ### We no longer need the test ap_os_is_filename_valid() here
- * since apr_stat isn't a posix thing - it's apr_stat's responsibility
- * to handle whatever path string arrives at it's door - by platform
- * and volume restrictions as applicable...
- * TODO: This code becomes even simpler if apr_stat grows
- * an APR_PATHINCOMPLETE result to indicate that we are staring at
- * an partial virtual root. Only OS2/Win32/Netware need apply it :-)
- */
- rv = apr_stat(&r->finfo, path, APR_FINFO_MIN, r->pool);
-
- if (cp != end)
- *cp = '/';
-
- if (rv == APR_SUCCESS || rv == APR_INCOMPLETE) {
- /*
- * Aha! Found something. If it was a directory, we will search
- * contents of that directory for a multi_match, so the PATH_INFO
- * argument starts with the component after that.
- */
- if (r->finfo.filetype == APR_DIR && last_cp) {
- r->finfo.filetype = APR_NOFILE; /* No such file... */
- cp = last_cp;
- }
-
- r->path_info = apr_pstrdup(r->pool, cp);
- *cp = '\0';
- return OK;
- }
-
- if (APR_STATUS_IS_ENOENT(rv) || APR_STATUS_IS_ENOTDIR(rv)) {
- last_cp = cp;
-
- while (--cp > path && *cp != '/')
- continue;
-
- while (cp > path && cp[-1] == '/')
- --cp;
- }
- else {
- if (APR_STATUS_IS_EACCES(rv))
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "access to %s denied", r->uri);
- else
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "access to %s failed", r->uri);
- return HTTP_FORBIDDEN;
- }
- }
- return OK;
-}
-
-AP_DECLARE(int) directory_walk(request_rec *r)
-{
- core_server_config *sconf = ap_get_module_config(r->server->module_config,
- &core_module);
- ap_conf_vector_t *per_dir_defaults = r->server->lookup_defaults;
- ap_conf_vector_t **sec = (ap_conf_vector_t **) sconf->sec->elts;
- int num_sec = sconf->sec->nelts;
- char *test_filename;
- char *test_dirname;
- int res;
- unsigned i, num_dirs;
- int j, test_filename_len;
-#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
- unsigned iStart = 1;
-#endif
- ap_conf_vector_t *entry_config;
- ap_conf_vector_t *this_conf;
- core_dir_config *entry_core;
-
- /*
- * Are we dealing with a file? If not, we can (hopefuly) safely assume we
- * have a handler that doesn't require one, but for safety's sake, and so
- * we have something find_types() can get something out of, fake one. But
- * don't run through the directory entries.
- */
-
- if (r->filename == NULL) {
- r->filename = apr_pstrdup(r->pool, r->uri);
- r->finfo.filetype = APR_NOFILE;
- r->per_dir_config = per_dir_defaults;
-
- return OK;
- }
-
- /*
- * Go down the directory hierarchy. Where we have to check for symlinks,
- * do so. Where a .htaccess file has permission to override anything,
- * try to find one. If either of these things fails, we could poke
- * around, see why, and adjust the lookup_rec accordingly --- this might
- * save us a call to get_path_info (with the attendant stat()s); however,
- * for the moment, that's not worth the trouble.
- *
- * Fake filenames (i.e. proxy:) only match Directory sections.
- */
-
- if (!ap_os_is_path_absolute(r->filename))
- {
- const char *entry_dir;
-
- for (j = 0; j < num_sec; ++j) {
-
- entry_config = sec[j];
- entry_core = ap_get_module_config(entry_config, &core_module);
- entry_dir = entry_core->d;
-
- this_conf = NULL;
- if (entry_core->r) {
- if (!ap_regexec(entry_core->r, r->filename, 0, NULL, 0))
- this_conf = entry_config;
- }
- else if (entry_core->d_is_fnmatch) {
- if (!apr_fnmatch(entry_dir, r->filename, 0))
- this_conf = entry_config;
- }
- else if (!strncmp(r->filename, entry_dir, strlen(entry_dir)))
- this_conf = entry_config;
-
- if (this_conf)
- per_dir_defaults = ap_merge_per_dir_configs(r->pool,
- per_dir_defaults,
- this_conf);
- }
-
- r->per_dir_config = per_dir_defaults;
-
- return OK;
- }
-
- /* XXX This needs to be rolled into APR, the APR function will not
- * be allowed to fold the case of any non-existant segment of the path:
- */
- r->filename = ap_os_case_canonical_filename(r->pool, r->filename);
-
- /* TODO This is rather silly right here, we should simply be setting
- * filename and path_info at the end of our directory_walk
- */
- res = get_path_info(r);
- if (res != OK) {
- return res;
- }
-
- /* XXX This becomes moot, and will already happen above for elements
- * that actually exist:
- */
- r->filename = ap_os_canonical_filename(r->pool, r->filename);
-
- test_filename = apr_pstrdup(r->pool, r->filename);
-
- /* XXX This becomes mute, since the APR canonical parsing will handle
- * 2slash and dot directory issues:
- */
- ap_no2slash(test_filename);
- num_dirs = ap_count_dirs(test_filename);
-
- /* XXX This needs to be rolled into APR: */
- if ((res = check_safe_file(r))) {
- return res;
- }
-
- test_filename_len = strlen(test_filename);
- if (test_filename[test_filename_len - 1] == '/')
- --num_dirs;
-
- if (r->finfo.filetype == APR_DIR)
- ++num_dirs;
-
- /*
- * We will use test_dirname as scratch space while we build directory
- * names during the walk. Profiling shows directory_walk to be a busy
- * function so we try to avoid allocating lots of extra memory here.
- * We need 2 extra bytes, one for trailing \0 and one because
- * make_dirstr_prefix will add potentially one extra /.
- */
- test_dirname = apr_palloc(r->pool, test_filename_len + 2);
-
- /* XXX These exception cases go away if apr_stat() returns the
- * APR_PATHINCOMPLETE status, so we skip hard filesystem testing
- * of the initial 'pseudo' elements:
- */
-
-#if defined(HAVE_UNC_PATHS)
- /* If the name is a UNC name, then do not perform any true file test
- * against the machine name (start at //machine/share/)
- * This is optimized to use the normal walk (skips the redundant '/' root)
- */
- if (num_dirs > 3 && test_filename[0] == '/' && test_filename[1] == '/')
- iStart = 4;
-#endif
-
-#if defined(NETWARE)
- /* If the name is a fully qualified volume name, then do not perform any
- * true file test on the machine name (start at machine/share:/)
- * XXX: The implementation eludes me at this moment...
- * Does this make sense? Please test!
- */
- if (num_dirs > 1 && strchr(test_filename, '/') < strchr(test_filename, ':'))
- iStart = 2;
-#endif
-
-#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
- /* Should match <Directory> sections starting from '/', not 'e:/'
- * (for example). WIN32/OS2/NETWARE do not have a single root directory,
- * they have one for each filesystem. Traditionally, Apache has treated
- * <Directory /> permissions as the base for the whole server, and this
- * tradition should probably be preserved.
- *
- * NOTE: MUST SYNC WITH ap_make_dirstr_prefix() CHANGE IN src/main/util.c
- */
- if (test_filename[0] == '/')
- i = 1;
- else
- i = 0;
-#else
- /* Normal File Systems are rooted at / */
- i = 1;
-#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
-
- /* j keeps track of which section we're on, see core_reorder_directories */
- j = 0;
- for (; i <= num_dirs; ++i) {
- int overrides_here;
- core_dir_config *core_dir = ap_get_module_config(per_dir_defaults,
- &core_module);
-
- /*
- * XXX: this could be made faster by only copying the next component
- * rather than copying the entire thing all over.
- */
- ap_make_dirstr_prefix(test_dirname, test_filename, i);
-
- /*
- * Do symlink checks first, because they are done with the
- * permissions appropriate to the *parent* directory...
- */
-
-#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
- /* Test only legal names against the real filesystem */
- if (i >= iStart)
-#endif
- if ((res = check_symlinks(test_dirname, core_dir->opts, r->pool))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Symbolic link not allowed: %s", test_dirname);
- return res;
- }
-
- /*
- * Begin *this* level by looking for matching <Directory> sections
- * from access.conf.
- */
-
- for (; j < num_sec; ++j) {
- char *entry_dir;
-
- entry_config = sec[j];
- entry_core = ap_get_module_config(entry_config, &core_module);
- entry_dir = entry_core->d;
-
- if (entry_core->r
- || !ap_os_is_path_absolute(entry_dir)
-#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
- /* To account for the top-level "/" directory when i == 0
- * XXX: The net test may be wrong... may fail ap_os_is_path_absolute
- */
- || (entry_core->d_components > 1
- && entry_core->d_components > i)
-#else
- || entry_core->d_components > i
-#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
- )
- break;
-
- this_conf = NULL;
- if (entry_core->d_is_fnmatch) {
- if (!apr_fnmatch(entry_dir, test_dirname, FNM_PATHNAME)) {
- this_conf = entry_config;
- }
- }
- else if (!strcmp(test_dirname, entry_dir))
- this_conf = entry_config;
-
- if (this_conf) {
- per_dir_defaults = ap_merge_per_dir_configs(r->pool,
- per_dir_defaults,
- this_conf);
- core_dir = ap_get_module_config(per_dir_defaults,
- &core_module);
- }
-#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
- /* So that other top-level directory sections (e.g. "e:/") aren't
- * skipped when i == 0
- * XXX: I don't get you here, Tim... That's a level 1 section, but
- * we are at level 0. Did you mean fast-forward to the next?
- */
- else if (!i)
- break;
-#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
- }
- overrides_here = core_dir->override;
-
- /* If .htaccess files are enabled, check for one. */
-
-#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
- /* Test only legal names against the real filesystem */
- if (i >= iStart)
-#endif
- if (overrides_here) {
- ap_conf_vector_t *htaccess_conf = NULL;
-
- res = ap_parse_htaccess(&htaccess_conf, r, overrides_here,
- apr_pstrdup(r->pool, test_dirname),
- sconf->access_name);
- if (res)
- return res;
-
- if (htaccess_conf) {
- per_dir_defaults = ap_merge_per_dir_configs(r->pool,
- per_dir_defaults,
- htaccess_conf);
- r->per_dir_config = per_dir_defaults;
- }
- }
- }
-
- /*
- * There's two types of IS_SPECIAL sections (see http_core.c), and we've
- * already handled the proxy:-style stuff. Now we'll deal with the
- * regexes.
- */
- for (; j < num_sec; ++j) {
-
- entry_config = sec[j];
- entry_core = ap_get_module_config(entry_config, &core_module);
-
- if (entry_core->r) {
- if (!ap_regexec(entry_core->r, test_dirname, 0, NULL, REG_NOTEOL)) {
- per_dir_defaults = ap_merge_per_dir_configs(r->pool,
- per_dir_defaults,
- entry_config);
- }
- }
- }
- r->per_dir_config = per_dir_defaults;
-
- /*
- * Symlink permissions are determined by the parent. If the request is
- * for a directory then applying the symlink test here would use the
- * permissions of the directory as opposed to its parent. Consider a
- * symlink pointing to a dir with a .htaccess disallowing symlinks. If
- * you access /symlink (or /symlink/) you would get a 403 without this
- * S_ISDIR test. But if you accessed /symlink/index.html, for example,
- * you would *not* get the 403.
- */
- if (r->finfo.filetype != APR_DIR
- && (res = check_symlinks(r->filename, ap_allow_options(r), r->pool))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Symbolic link not allowed: %s", r->filename);
- return res;
- }
- return OK; /* Can only "fail" if access denied by the
- * symlink goop. */
-}
-
-AP_DECLARE(int) location_walk(request_rec *r)
-{
- core_server_config *sconf = ap_get_module_config(r->server->module_config,
- &core_module);
- ap_conf_vector_t *per_dir_defaults = r->per_dir_config;
- ap_conf_vector_t **url = (ap_conf_vector_t **) sconf->sec_url->elts;
- int len, num_url = sconf->sec_url->nelts;
- char *test_location;
- ap_conf_vector_t *this_conf;
- ap_conf_vector_t *entry_config;
- core_dir_config *entry_core;
- char *entry_url;
- int j;
-
- if (!num_url) {
- return OK;
- }
-
- /* Location and LocationMatch differ on their behaviour w.r.t. multiple
- * slashes. Location matches multiple slashes with a single slash,
- * LocationMatch doesn't. An exception, for backwards brokenness is
- * absoluteURIs... in which case neither match multiple slashes.
- */
- if (r->uri[0] != '/') {
- test_location = r->uri;
- }
- else {
- test_location = apr_pstrdup(r->pool, r->uri);
- ap_no2slash(test_location);
- }
-
- /* Go through the location entries, and check for matches. */
-
- /* we apply the directive sections in some order;
- * should really try them with the most general first.
- */
- for (j = 0; j < num_url; ++j) {
-
- entry_config = url[j];
-
- entry_core = ap_get_module_config(entry_config, &core_module);
- entry_url = entry_core->d;
-
- len = strlen(entry_url);
-
- this_conf = NULL;
-
- if (entry_core->r) {
- if (!ap_regexec(entry_core->r, r->uri, 0, NULL, 0))
- this_conf = entry_config;
- }
- else if (entry_core->d_is_fnmatch) {
- if (!apr_fnmatch(entry_url, test_location, FNM_PATHNAME)) {
- this_conf = entry_config;
- }
- }
- else if (!strncmp(test_location, entry_url, len) &&
- (entry_url[len - 1] == '/' ||
- test_location[len] == '/' || test_location[len] == '\0'))
- this_conf = entry_config;
-
- if (this_conf)
- per_dir_defaults = ap_merge_per_dir_configs(r->pool,
- per_dir_defaults,
- this_conf);
- }
- r->per_dir_config = per_dir_defaults;
-
- return OK;
-}
-
-AP_DECLARE(int) file_walk(request_rec *r)
-{
- core_dir_config *conf = ap_get_module_config(r->per_dir_config,
- &core_module);
- ap_conf_vector_t *per_dir_defaults = r->per_dir_config;
- ap_conf_vector_t **file = (ap_conf_vector_t **) conf->sec->elts;
- int num_files = conf->sec->nelts;
- char *test_file;
-
- /* get the basename */
- test_file = strrchr(r->filename, '/');
- if (test_file == NULL) {
- test_file = r->filename;
- }
- else {
- ++test_file;
- }
-
- /* Go through the file entries, and check for matches. */
-
- if (num_files) {
- ap_conf_vector_t *this_conf;
- ap_conf_vector_t *entry_config;
- core_dir_config *entry_core;
- char *entry_file;
- int j;
-
- /* we apply the directive sections in some order;
- * should really try them with the most general first.
- */
- for (j = 0; j < num_files; ++j) {
-
- entry_config = file[j];
-
- entry_core = ap_get_module_config(entry_config, &core_module);
- entry_file = entry_core->d;
-
- this_conf = NULL;
-
- if (entry_core->r) {
- if (!ap_regexec(entry_core->r, test_file, 0, NULL, 0))
- this_conf = entry_config;
- }
- else if (entry_core->d_is_fnmatch) {
- if (!apr_fnmatch(entry_file, test_file, FNM_PATHNAME)) {
- this_conf = entry_config;
- }
- }
- else if (!strcmp(test_file, entry_file)) {
- this_conf = entry_config;
- }
-
- if (this_conf)
- per_dir_defaults = ap_merge_per_dir_configs(r->pool,
- per_dir_defaults,
- this_conf);
- }
- r->per_dir_config = per_dir_defaults;
- }
- return OK;
-}
-
-/*****************************************************************
- *
- * The sub_request mechanism.
- *
- * Fns to look up a relative URI from, e.g., a map file or SSI document.
- * These do all access checks, etc., but don't actually run the transaction
- * ... use run_sub_req below for that. Also, be sure to use destroy_sub_req
- * as appropriate if you're likely to be creating more than a few of these.
- * (An early Apache version didn't destroy the sub_reqs used in directory
- * indexing. The result, when indexing a directory with 800-odd files in
- * it, was massively excessive storage allocation).
- *
- * Note more manipulation of protocol-specific vars in the request
- * structure...
- */
-
-static request_rec *make_sub_request(const request_rec *r)
-{
- apr_pool_t *rrp;
- request_rec *rr;
-
- apr_pool_create(&rrp, r->pool);
- rr = apr_pcalloc(rrp, sizeof(request_rec));
- rr->pool = rrp;
- return rr;
-}
-
-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_sub_req_output_filter(ap_filter_t *f,
- apr_bucket_brigade *bb)
-{
- apr_bucket *e = APR_BRIGADE_LAST(bb);
-
- if (APR_BUCKET_IS_EOS(e)) {
- apr_bucket_delete(e);
- }
- ap_pass_brigade(f->next, bb);
- return APR_SUCCESS;
-}
-
-
-AP_DECLARE(int) ap_some_auth_required(request_rec *r)
-{
- /* Is there a require line configured for the type of *this* req? */
-
- const apr_array_header_t *reqs_arr = ap_requires(r);
- require_line *reqs;
- int i;
-
- if (!reqs_arr)
- return 0;
-
- reqs = (require_line *) reqs_arr->elts;
-
- for (i = 0; i < reqs_arr->nelts; ++i)
- if (reqs[i].method_mask & (1 << r->method_number))
- return 1;
-
- return 0;
-}
-
-AP_DECLARE(request_rec *) ap_sub_req_method_uri(const char *method,
- const char *new_file,
- const request_rec *r,
- ap_filter_t *next_filter)
-{
- request_rec *rnew;
- int res;
- char *udir;
-
- rnew = make_sub_request(r);
- rnew->hostname = r->hostname;
- rnew->request_time = r->request_time;
- rnew->connection = r->connection;
- rnew->server = r->server;
-
- rnew->request_config = ap_create_request_config(rnew->pool);
-
- rnew->htaccess = r->htaccess;
- rnew->per_dir_config = r->server->lookup_defaults;
- rnew->allowed_methods = ap_make_method_list(rnew->pool, 2);
-
- /* make a copy of the allowed-methods list */
- ap_copy_method_list(rnew->allowed_methods, r->allowed_methods);
-
- /* start with the same set of output filters */
- if (next_filter) {
- rnew->output_filters = next_filter;
- }
- else {
- rnew->output_filters = r->output_filters;
- }
- ap_add_output_filter("SUBREQ_CORE", NULL, rnew, rnew->connection);
-
- /* no input filters for a subrequest */
-
- ap_set_sub_req_protocol(rnew, r);
-
- /* We have to run this after ap_set_sub_req_protocol, or the r->main
- * pointer won't be setup
- */
- ap_run_create_request(rnew);
-
- /* would be nicer to pass "method" to ap_set_sub_req_protocol */
- rnew->method = method;
- rnew->method_number = ap_method_number_of(method);
-
- if (new_file[0] == '/')
- ap_parse_uri(rnew, new_file);
- else {
- udir = ap_make_dirstr_parent(rnew->pool, r->uri);
- udir = ap_escape_uri(rnew->pool, udir); /* re-escape it */
- ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file));
- }
-
- res = ap_unescape_url(rnew->uri);
- if (res) {
- rnew->status = res;
- return rnew;
- }
-
- ap_getparents(rnew->uri);
-
- if ((res = location_walk(rnew))) {
- rnew->status = res;
- return rnew;
- }
-
- res = ap_run_translate_name(rnew);
- if (res) {
- rnew->status = res;
- return rnew;
- }
-
- /*
- * We could be clever at this point, and avoid calling directory_walk,
- * etc. However, we'd need to test that the old and new filenames contain
- * the same directory components, so it would require duplicating the
- * start of translate_name. Instead we rely on the cache of .htaccess
- * results.
- *
- * NB: directory_walk() clears the per_dir_config, so we don't inherit
- * from location_walk() above
- */
-
- if ((res = directory_walk(rnew))
- || (res = file_walk(rnew))
- || (res = location_walk(rnew))
- || ((ap_satisfies(rnew) == SATISFY_ALL
- || ap_satisfies(rnew) == SATISFY_NOSPEC)
- ? ((res = ap_run_access_checker(rnew))
- || (ap_some_auth_required(rnew)
- && ((res = ap_run_check_user_id(rnew))
- || (res = ap_run_auth_checker(rnew)))))
- : ((res = ap_run_access_checker(rnew))
- && (!ap_some_auth_required(rnew)
- || ((res = ap_run_check_user_id(rnew))
- || (res = ap_run_auth_checker(rnew)))))
- )
- || (res = ap_run_type_checker(rnew))
- || (res = ap_run_fixups(rnew))
- ) {
- rnew->status = res;
- }
- return rnew;
-}
-
-AP_DECLARE(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
- const request_rec *r,
- ap_filter_t *next_filter)
-{
- return ap_sub_req_method_uri("GET", new_file, r, next_filter);
-}
-
-AP_DECLARE(request_rec *) ap_sub_req_lookup_file(const char *new_file,
- const request_rec *r,
- ap_filter_t *next_filter)
-{
- request_rec *rnew;
- int res;
- char *fdir;
-
- rnew = make_sub_request(r);
- rnew->hostname = r->hostname;
- rnew->request_time = r->request_time;
- rnew->connection = r->connection;
- rnew->server = r->server;
-
- rnew->request_config = ap_create_request_config(rnew->pool);
-
- rnew->htaccess = r->htaccess;
- rnew->chunked = r->chunked;
- rnew->allowed_methods = ap_make_method_list(rnew->pool, 2);
-
- /* make a copy of the allowed-methods list */
- ap_copy_method_list(rnew->allowed_methods, r->allowed_methods);
-
- /* start with the same set of output filters */
- if (next_filter) {
- rnew->output_filters = next_filter;
- }
- else {
- rnew->output_filters = r->output_filters;
- }
- ap_add_output_filter("SUBREQ_CORE", NULL, rnew, rnew->connection);
-
- /* no input filters for a subrequest */
-
- ap_set_sub_req_protocol(rnew, r);
-
- /* We have to run this after ap_set_sub_req_protocol, or the r->main
- * pointer won't be setup
- */
- ap_run_create_request(rnew);
-
- fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
-
- /*
- * Check for a special case... if there are no '/' characters in new_file
- * at all, then we are looking at a relative lookup in the same
- * directory. That means we won't have to redo directory_walk, and we may
- * not even have to redo access checks.
- */
-
- if (ap_strchr_c(new_file, '/') == NULL) {
- char *udir = ap_make_dirstr_parent(rnew->pool, r->uri);
- apr_status_t rv;
-
- rnew->uri = ap_make_full_path(rnew->pool, udir, new_file);
- rnew->filename = ap_make_full_path(rnew->pool, fdir, new_file);
- ap_parse_uri(rnew, rnew->uri); /* fill in parsed_uri values */
-
- if (((rv = apr_stat(&rnew->finfo, rnew->filename,
- APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS)
- && (rv != APR_INCOMPLETE)) {
- rnew->finfo.filetype = 0;
- }
-
- if ((res = check_safe_file(rnew))) {
- rnew->status = res;
- return rnew;
- }
-
- rnew->per_dir_config = r->per_dir_config;
-
- /*
- * no matter what, if it's a subdirectory, we need to re-run
- * directory_walk
- */
- if (rnew->finfo.filetype == APR_DIR) {
- res = directory_walk(rnew);
- if (!res) {
- res = file_walk(rnew);
- }
- }
- else {
- if ((res = check_symlinks(rnew->filename, ap_allow_options(rnew),
- rnew->pool))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, rnew,
- "Symbolic link not allowed: %s", rnew->filename);
- rnew->status = res;
- return rnew;
- }
- /*
- * do a file_walk, if it doesn't change the per_dir_config then
- * we know that we don't have to redo all the access checks
- */
- if ((res = file_walk(rnew))) {
- rnew->status = res;
- return rnew;
- }
- if (rnew->per_dir_config == r->per_dir_config) {
- if ((res = ap_run_type_checker(rnew)) || (res = ap_run_fixups(rnew))) {
- rnew->status = res;
- }
- return rnew;
- }
- }
- }
- else {
- /* XXX: @@@: What should be done with the parsed_uri values? */
- ap_parse_uri(rnew, new_file); /* fill in parsed_uri values */
- /*
- * XXX: this should be set properly like it is in the same-dir case
- * but it's actually sometimes to impossible to do it... because the
- * file may not have a uri associated with it -djg
- */
- rnew->uri = "INTERNALLY GENERATED file-relative req";
- rnew->filename = ((ap_os_is_path_absolute(new_file)) ?
- apr_pstrdup(rnew->pool, new_file) :
- ap_make_full_path(rnew->pool, fdir, new_file));
- rnew->per_dir_config = r->server->lookup_defaults;
- res = directory_walk(rnew);
- if (!res) {
- res = file_walk(rnew);
- }
- }
-
- if (res
- || ((ap_satisfies(rnew) == SATISFY_ALL
- || ap_satisfies(rnew) == SATISFY_NOSPEC)
- ? ((res = ap_run_access_checker(rnew))
- || (ap_some_auth_required(rnew)
- && ((res = ap_run_check_user_id(rnew))
- || (res = ap_run_auth_checker(rnew)))))
- : ((res = ap_run_access_checker(rnew))
- && (!ap_some_auth_required(rnew)
- || ((res = ap_run_check_user_id(rnew))
- || (res = ap_run_auth_checker(rnew)))))
- )
- || (res = ap_run_type_checker(rnew))
- || (res = ap_run_fixups(rnew))
- ) {
- rnew->status = res;
- }
- return rnew;
-}
-
-AP_DECLARE(int) ap_run_sub_req(request_rec *r)
-{
- int retval;
-
- /* see comments in process_request_internal() */
- ap_run_insert_filter(r);
- retval = ap_invoke_handler(r);
- ap_finalize_sub_req_protocol(r);
- return retval;
-}
-
-AP_DECLARE(void) ap_destroy_sub_req(request_rec *r)
-{
- /* Reclaim the space */
- apr_pool_destroy(r->pool);
-}
-
-/*
- * Function to set the r->mtime field to the specified value if it's later
- * than what's already there.
- */
-AP_DECLARE(void) ap_update_mtime(request_rec *r, apr_time_t dependency_mtime)
-{
- if (r->mtime < dependency_mtime) {
- r->mtime = dependency_mtime;
- }
-}
-
-/*
- * Is it the initial main request, which we only get *once* per HTTP request?
- */
-AP_DECLARE(int) ap_is_initial_req(request_rec *r)
-{
- return
- (r->main == NULL) /* otherwise, this is a sub-request */
- &&
- (r->prev == NULL); /* otherwise, this is an internal redirect */
-}
-
diff --git a/server/rfc1413.c b/server/rfc1413.c
deleted file mode 100644
index 40d221bc10..0000000000
--- a/server/rfc1413.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* TODO - put timeouts back in */
-/*
- * rfc1413() speaks a common subset of the RFC 1413, AUTH, TAP and IDENT
- * protocols. The code queries an RFC 1413 etc. compatible daemon on a remote
- * host to look up the owner of a connection. The information should not be
- * used for authentication purposes. This routine intercepts alarm signals.
- *
- * Diagnostics are reported through syslog(3).
- *
- * Author: Wietse Venema, Eindhoven University of Technology,
- * The Netherlands.
- */
-
-/* Some small additions for Apache --- ditch the "sccsid" var if
- * compiling with gcc (it *has* changed), include ap_config.h for the
- * prototypes it defines on at least one system (SunlOSs) which has
- * them missing from the standard header files, and one minor change
- * below (extra parens around assign "if (foo = bar) ..." to shut up
- * gcc -Wall).
- */
-
-/* Rewritten by David Robinson */
-
-#include "apr.h"
-#include "apr_network_io.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STDIO
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h" /* for server_rec, conn_rec, etc. */
-#include "http_log.h" /* for aplog_error */
-#include "rfc1413.h"
-#include "http_main.h" /* set_callback_and_alarm */
-#include "util_ebcdic.h"
-
-/* Local stuff. */
-/* Semi-well-known port */
-#define RFC1413_PORT 113
-/* maximum allowed length of userid */
-#define RFC1413_USERLEN 512
-/* rough limit on the amount of data we accept. */
-#define RFC1413_MAXDATA 1000
-
-#ifndef RFC1413_TIMEOUT
-#define RFC1413_TIMEOUT 30
-#endif
-#define FROM_UNKNOWN "unknown"
-
-int ap_rfc1413_timeout = RFC1413_TIMEOUT; /* Global so it can be changed */
-
-static apr_status_t rfc1413_connect(apr_socket_t **newsock, conn_rec *conn,
- server_rec *srv)
-{
- apr_status_t rv;
- apr_sockaddr_t *localsa, *destsa;
-
- if ((rv = apr_sockaddr_info_get(&localsa, conn->local_ip, APR_UNSPEC,
- 0, /* ephemeral port */
- 0, conn->pool)) != APR_SUCCESS) {
- /* This should not fail since we have a numeric address string
- * as the host. */
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
- "rfc1413: apr_sockaddr_info_get(%s) failed",
- conn->local_ip);
- return rv;
- }
-
- if ((rv = apr_sockaddr_info_get(&destsa, conn->remote_ip,
- localsa->sa.sin.sin_family, /* has to match */
- RFC1413_PORT, 0, conn->pool)) != APR_SUCCESS) {
- /* This should not fail since we have a numeric address string
- * as the host. */
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
- "rfc1413: apr_sockaddr_info_get(%s) failed",
- conn->remote_ip);
- return rv;
- }
-
- if ((rv = apr_socket_create(newsock,
- localsa->sa.sin.sin_family, /* has to match */
- SOCK_STREAM, conn->pool)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
- "rfc1413: error creating query socket");
- return rv;
- }
-
- if ((rv = apr_setsocketopt(*newsock, APR_SO_TIMEOUT,
- (apr_int32_t)(ap_rfc1413_timeout
- * APR_USEC_PER_SEC)))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
- "rfc1413: error setting query socket timeout");
- apr_socket_close(*newsock);
- return rv;
- }
-
-/*
- * Bind the local and remote ends of the query socket to the same
- * IP addresses as the connection under investigation. We go
- * through all this trouble because the local or remote system
- * might have more than one network address. The RFC1413 etc.
- * client sends only port numbers; the server takes the IP
- * addresses from the query socket.
- */
-
- if ((rv = apr_bind(*newsock, localsa)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
- "rfc1413: Error binding query socket to local port");
- apr_socket_close(*newsock);
- return rv;
- }
-
-/*
- * errors from connect usually imply the remote machine doesn't support
- * the service; don't log such an error
- */
- if ((rv = apr_connect(*newsock, destsa)) != APR_SUCCESS) {
- apr_socket_close(*newsock);
- return rv;
- }
-
- return APR_SUCCESS;
-}
-
-static apr_status_t rfc1413_query(apr_socket_t *sock, conn_rec *conn,
- server_rec *srv)
-{
- apr_port_t rmt_port, our_port;
- apr_port_t sav_rmt_port, sav_our_port;
- apr_size_t i;
- char *cp;
- char buffer[RFC1413_MAXDATA + 1];
- char user[RFC1413_USERLEN + 1]; /* XXX */
- apr_size_t buflen;
- apr_sockaddr_t *localsa;
-
- apr_socket_addr_get(&localsa, APR_LOCAL, sock);
- apr_sockaddr_port_get(&sav_our_port, localsa);
- sav_rmt_port = RFC1413_PORT;
-
- /* send the data */
- buflen = apr_snprintf(buffer, sizeof(buffer), "%hu,%hu\r\n", sav_rmt_port,
- sav_our_port);
- ap_xlate_proto_to_ascii(buffer, buflen);
-
- /* send query to server. Handle short write. */
- i = 0;
- while (i < buflen) {
- apr_size_t j = strlen(buffer + i);
- apr_status_t status;
- status = apr_send(sock, buffer+i, &j);
- if (status != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
- "write: rfc1413: error sending request");
- return status;
- }
- else if (j > 0) {
- i+=j;
- }
- }
-
- /*
- * Read response from server. - the response should be newline
- * terminated according to rfc - make sure it doesn't stomp its
- * way out of the buffer.
- */
-
- i = 0;
- memset(buffer, '\0', sizeof(buffer));
- /*
- * Note that the strchr function below checks for \012 instead of '\n'
- * this allows it to work on both ASCII and EBCDIC machines.
- */
- while((cp = strchr(buffer, '\012')) == NULL && i < sizeof(buffer) - 1) {
- apr_size_t j = sizeof(buffer) - 1 - i;
- apr_status_t status;
- status = apr_recv(sock, buffer+i, &j);
- if (status != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
- "read: rfc1413: error reading response");
- return status;
- }
- else if (j > 0) {
- i+=j;
- }
- else if (status == APR_SUCCESS && j == 0) {
- /* Oops... we ran out of data before finding newline */
- return APR_EINVAL;
- }
- }
-
-/* RFC1413_USERLEN = 512 */
- ap_xlate_proto_from_ascii(buffer, i);
- if (sscanf(buffer, "%hu , %hu : USERID :%*[^:]:%512s", &rmt_port, &our_port,
- user) != 3 || sav_rmt_port != rmt_port
- || sav_our_port != our_port)
- return APR_EINVAL;
-
- /*
- * Strip trailing carriage return. It is part of the
- * protocol, not part of the data.
- */
-
- if ((cp = strchr(user, '\r')))
- *cp = '\0';
-
- conn->remote_logname = apr_pstrdup(conn->pool, user);
-
- return APR_SUCCESS;
-}
-
-char *ap_rfc1413(conn_rec *conn, server_rec *srv)
-{
- apr_socket_t *sock;
- apr_status_t rv;
-
- rv = rfc1413_connect(&sock, conn, srv);
- if (rv == APR_SUCCESS) {
- rv = rfc1413_query(sock, conn, srv);
- apr_socket_close(sock);
- }
- if (rv != APR_SUCCESS) {
- conn->remote_logname = FROM_UNKNOWN;
- }
- return conn->remote_logname;
-}
diff --git a/server/scoreboard.c b/server/scoreboard.c
deleted file mode 100644
index d93a84aaec..0000000000
--- a/server/scoreboard.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_portable.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "ap_mpm.h"
-
-#include "mpm.h"
-#include "scoreboard.h"
-
-AP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
-AP_DECLARE_DATA const char *ap_scoreboard_fname=NULL;
-AP_DECLARE_DATA int ap_extended_status = 0;
-AP_DECLARE_DATA apr_time_t ap_restart_time = 0;
-
-#if APR_HAS_SHARED_MEMORY
-#include "apr_shmem.h"
-static apr_shmem_t *scoreboard_shm = NULL;
-#endif
-/*
- * ToDo:
- * This function should be renamed to cleanup_shared
- * and it should handle cleaning up a scoreboard shared
- * between processes using any form of IPC (file, shared memory
- * segment, etc.). Leave it as is now because it is being used
- * by various MPMs.
- */
-static apr_status_t ap_cleanup_shared_mem(void *d)
-{
-#if APR_HAS_SHARED_MEMORY
- apr_shm_free(scoreboard_shm, ap_scoreboard_image);
- ap_scoreboard_image = NULL;
- apr_shm_destroy(scoreboard_shm);
-#endif
- return APR_SUCCESS;
-}
-
-/* ToDo: This function should be made to handle setting up
- * a scoreboard shared between processes using any IPC technique,
- * not just a shared memory segment
- */
-static void setup_shared(apr_pool_t *p)
-{
-#if APR_HAS_SHARED_MEMORY
- char buf[512];
- char errmsg[120];
- const char *fname;
- apr_status_t rv;
-
- fname = ap_server_root_relative(p, ap_scoreboard_fname);
- rv = apr_shm_init(&scoreboard_shm, SCOREBOARD_SIZE, fname, p);
- if (rv != APR_SUCCESS) {
- apr_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard: %s",
- ap_server_argv0, apr_strerror(rv, errmsg, sizeof errmsg));
- fprintf(stderr, "%s\n", buf);
- exit(APEXIT_INIT);
- }
- ap_scoreboard_image = apr_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL) {
- apr_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
- ap_server_argv0);
- perror(buf); /* o.k. since MM sets errno */
- apr_shm_destroy(scoreboard_shm);
- exit(APEXIT_INIT);
- }
- ap_scoreboard_image->global.running_generation = 0;
-#endif
-}
-
-AP_DECLARE(void) reopen_scoreboard(apr_pool_t *p)
-{
-}
-
-/* ap_cleanup_scoreboard
- *
- */
-apr_status_t ap_cleanup_scoreboard(void *d) {
- if (ap_scoreboard_image == NULL)
- return APR_SUCCESS;
- if (ap_scoreboard_image->global.sb_type == SB_SHARED) {
- ap_cleanup_shared_mem(NULL);
- }
- else {
- free(ap_scoreboard_image);
- ap_scoreboard_image = NULL;
- }
- return APR_SUCCESS;
-}
-
-/* ap_create_scoreboard(apr_pool_t*, ap_scoreboard_e t)
- *
- * Create or reinit an existing scoreboard. The MPM can control whether
- * the scoreboard is shared across multiple processes or not
- */
-AP_DECLARE(void) ap_create_scoreboard(apr_pool_t *p, ap_scoreboard_e sb_type)
-{
- int running_gen = 0;
- if (ap_scoreboard_image)
- running_gen = ap_scoreboard_image->global.running_generation;
- if (ap_scoreboard_image == NULL) {
- if (sb_type == SB_SHARED) {
- setup_shared(p);
- }
- else {
- /* A simple malloc will suffice */
- char buf[512];
- ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
- if (ap_scoreboard_image == NULL) {
- apr_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
- ap_server_argv0);
- perror(buf); /* o.k. since MM sets errno */
- exit(APEXIT_INIT);
- }
- }
- }
- memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
- ap_scoreboard_image->global.sb_type = sb_type;
- ap_scoreboard_image->global.running_generation = running_gen;
- ap_restart_time = apr_time_now();
- apr_pool_cleanup_register(p, NULL, ap_cleanup_scoreboard, apr_pool_cleanup_null);
-}
-
-/* Routines called to deal with the scoreboard image
- * --- note that we do *not* need write locks, since update_child_status
- * only updates a *single* record in place, and only one process writes to
- * a given scoreboard slot at a time (either the child process owning that
- * slot, or the parent, noting that the child has died).
- *
- * As a final note --- setting the score entry to getpid() is always safe,
- * since when the parent is writing an entry, it's only noting SERVER_DEAD
- * anyway.
- */
-
-void ap_sync_scoreboard_image(void)
-{
-}
-
-AP_DECLARE(int) ap_exists_scoreboard_image(void)
-{
- return (ap_scoreboard_image ? 1 : 0);
-}
-
-static APR_INLINE void put_scoreboard_info(int child_num, int thread_num,
- short_score *new_score_rec)
-{
- /* XXX - needs to be fixed to account for threads */
-#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
- force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
-#endif
-}
-
-void update_scoreboard_global(void)
-{
-#ifdef SCOREBOARD_FILE
- lseek(scoreboard_fd,
- (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
- force_write(scoreboard_fd, &ap_scoreboard_image->global,
- sizeof ap_scoreboard_image->global);
-#endif
-}
-
-AP_DECLARE(void) ap_increment_counts(int child_num, int thread_num, request_rec *r)
-{
- short_score *ss;
-
- ss = &ap_scoreboard_image->servers[child_num][thread_num];
-
-#ifdef HAVE_TIMES
- times(&ss->times);
-#endif
- ss->access_count++;
- ss->my_access_count++;
- ss->conn_count++;
- ss->bytes_served += r->bytes_sent;
- ss->my_bytes_served += r->bytes_sent;
- ss->conn_bytes += r->bytes_sent;
-
- put_scoreboard_info(child_num, thread_num, ss);
-}
-
-AP_DECLARE(int) find_child_by_pid(apr_proc_t *pid)
-{
- int i;
- int max_daemons_limit;
-
- ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons_limit);
-
- for (i = 0; i < max_daemons_limit; ++i)
- if (ap_scoreboard_image->parent[i].pid == pid->pid)
- return i;
-
- return -1;
-}
-
-int ap_update_child_status(int child_num, int thread_num, int status, request_rec *r)
-{
- int old_status;
- short_score *ss;
- parent_score *ps;
-
- if (child_num < 0)
- return -1;
-
- ss = &ap_scoreboard_image->servers[child_num][thread_num];
- old_status = ss->status;
- ss->status = status;
-
- ps = &ap_scoreboard_image->parent[child_num];
-
- if ((status == SERVER_READY || status == SERVER_ACCEPTING)
- && old_status == SERVER_STARTING) {
- ss->thread_num = child_num * HARD_SERVER_LIMIT + thread_num;
- ps->worker_threads = ap_threads_per_child;
- }
-
- if (ap_extended_status) {
- if (status == SERVER_READY || status == SERVER_DEAD) {
- /*
- * Reset individual counters
- */
- if (status == SERVER_DEAD) {
- ss->my_access_count = 0L;
- ss->my_bytes_served = 0L;
- }
- ss->conn_count = (unsigned short) 0;
- ss->conn_bytes = (unsigned long) 0;
- }
- if (r) {
- conn_rec *c = r->connection;
- apr_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
- REMOTE_NOLOOKUP, NULL), sizeof(ss->client));
- if (r->the_request == NULL) {
- apr_cpystrn(ss->request, "NULL", sizeof(ss->request));
- } else if (r->parsed_uri.password == NULL) {
- apr_cpystrn(ss->request, r->the_request, sizeof(ss->request));
- } else {
- /* Don't reveal the password in the server-status view */
- apr_cpystrn(ss->request, apr_pstrcat(r->pool, r->method, " ",
- ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
- r->assbackwards ? NULL : " ", r->protocol, NULL),
- sizeof(ss->request));
- }
- ss->vhostrec = r->server;
- }
- }
-
- put_scoreboard_info(child_num, thread_num, ss);
- return old_status;
-}
-
-void ap_time_process_request(int child_num, int thread_num, int status)
-{
- short_score *ss;
-
- if (child_num < 0)
- return;
-
- ss = &ap_scoreboard_image->servers[child_num][thread_num];
-
- if (status == START_PREQUEST) {
- ss->start_time = apr_time_now();
- }
- else if (status == STOP_PREQUEST) {
- ss->stop_time = apr_time_now();
- }
- put_scoreboard_info(child_num, thread_num, ss);
-}
-
diff --git a/server/util.c b/server/util.c
deleted file mode 100644
index 7ff05caa6e..0000000000
--- a/server/util.c
+++ /dev/null
@@ -1,1907 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * util.c: string utility things
- *
- * 3/21/93 Rob McCool
- * 1995-96 Many changes by the Apache Software Foundation
- *
- */
-
-/* Debugging aid:
- * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls
- * #define DEBUG_CFG_LINES to trace every line read from the config files
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STDIO
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_NETDB_H
-#include <netdb.h> /* for gethostbyname() */
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "apr_base64.h"
-#include "httpd.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "http_config.h"
-#include "util_ebcdic.h"
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-
-/* A bunch of functions in util.c scan strings looking for certain characters.
- * To make that more efficient we encode a lookup table. The test_char_table
- * is generated automatically by gen_test_char.c.
- */
-#include "test_char.h"
-
-/* we assume the folks using this ensure 0 <= c < 256... which means
- * you need a cast to (unsigned char) first, you can't just plug a
- * char in here and get it to work, because if char is signed then it
- * will first be sign extended.
- */
-#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
-
-/*
- * Examine a field value (such as a media-/content-type) string and return
- * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
- */
-AP_DECLARE(char *) ap_field_noparam(apr_pool_t *p, const char *intype)
-{
- const char *semi;
-
- if (intype == NULL) return NULL;
-
- semi = ap_strchr_c(intype, ';');
- if (semi == NULL) {
- return apr_pstrdup(p, intype);
- }
- else {
- while ((semi > intype) && apr_isspace(semi[-1])) {
- semi--;
- }
- return apr_pstrndup(p, intype, semi - intype);
- }
-}
-
-AP_DECLARE(char *) ap_ht_time(apr_pool_t *p, apr_time_t t, const char *fmt, int gmt)
-{
- apr_size_t retcode;
- char ts[MAX_STRING_LEN];
- char tf[MAX_STRING_LEN];
- apr_exploded_time_t xt;
-
- if (gmt) {
- const char *f;
- char *strp;
-
- apr_explode_gmt(&xt, t);
- /* Convert %Z to "GMT" and %z to "+0000";
- * on hosts that do not have a time zone string in struct tm,
- * strftime must assume its argument is local time.
- */
- for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)
- ; f++, strp++) {
- if (*f != '%') continue;
- switch (f[1]) {
- case '%':
- *++strp = *++f;
- break;
- case 'Z':
- *strp++ = 'G';
- *strp++ = 'M';
- *strp = 'T';
- f++;
- break;
- case 'z': /* common extension */
- *strp++ = '+';
- *strp++ = '0';
- *strp++ = '0';
- *strp++ = '0';
- *strp = '0';
- f++;
- break;
- }
- }
- *strp = '\0';
- fmt = tf;
- }
- else {
- apr_explode_localtime(&xt, t);
- }
-
- /* check return code? */
- apr_strftime(ts, &retcode, MAX_STRING_LEN, fmt, &xt);
- ts[MAX_STRING_LEN - 1] = '\0';
- return apr_pstrdup(p, ts);
-}
-
-/* Roy owes Rob beer. */
-/* Rob owes Roy dinner. */
-
-/* These legacy comments would make a lot more sense if Roy hadn't
- * replaced the old later_than() routine with util_date.c.
- *
- * Well, okay, they still wouldn't make any sense.
- */
-
-/* Match = 0, NoMatch = 1, Abort = -1
- * Based loosely on sections of wildmat.c by Rich Salz
- * Hmmm... shouldn't this really go component by component?
- */
-AP_DECLARE(int) ap_strcmp_match(const char *str, const char *exp)
-{
- int x, y;
-
- for (x = 0, y = 0; exp[y]; ++y, ++x) {
- if ((!str[x]) && (exp[y] != '*'))
- return -1;
- if (exp[y] == '*') {
- while (exp[++y] == '*');
- if (!exp[y])
- return 0;
- while (str[x]) {
- int ret;
- if ((ret = ap_strcmp_match(&str[x++], &exp[y])) != 1)
- return ret;
- }
- return -1;
- }
- else if ((exp[y] != '?') && (str[x] != exp[y]))
- return 1;
- }
- return (str[x] != '\0');
-}
-
-AP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *exp)
-{
- int x, y;
-
- for (x = 0, y = 0; exp[y]; ++y, ++x) {
- if ((!str[x]) && (exp[y] != '*'))
- return -1;
- if (exp[y] == '*') {
- while (exp[++y] == '*');
- if (!exp[y])
- return 0;
- while (str[x]) {
- int ret;
- if ((ret = ap_strcasecmp_match(&str[x++], &exp[y])) != 1)
- return ret;
- }
- return -1;
- }
- else if ((exp[y] != '?') && (apr_tolower(str[x]) != apr_tolower(exp[y])))
- return 1;
- }
- return (str[x] != '\0');
-}
-
-AP_DECLARE(int) ap_is_matchexp(const char *str)
-{
- register int x;
-
- for (x = 0; str[x]; x++)
- if ((str[x] == '*') || (str[x] == '?'))
- return 1;
- return 0;
-}
-
-/*
- * Here's a pool-based interface to POSIX regex's regcomp().
- * Note that we return regex_t instead of being passed one.
- * The reason is that if you use an already-used regex_t structure,
- * the memory that you've already allocated gets forgotten, and
- * regfree() doesn't clear it. So we don't allow it.
- */
-
-static apr_status_t regex_cleanup(void *preg)
-{
- regfree((regex_t *) preg);
- return APR_SUCCESS;
-}
-
-AP_DECLARE(regex_t *) ap_pregcomp(apr_pool_t *p, const char *pattern,
- int cflags)
-{
- regex_t *preg = apr_palloc(p, sizeof(regex_t));
-
- if (regcomp(preg, pattern, cflags)) {
- return NULL;
- }
-
- apr_pool_cleanup_register(p, (void *) preg, regex_cleanup, regex_cleanup);
-
- return preg;
-}
-
-AP_DECLARE(void) ap_pregfree(apr_pool_t *p, regex_t * reg)
-{
- regfree(reg);
- apr_pool_cleanup_kill(p, (void *) reg, regex_cleanup);
-}
-
-/*
- * Similar to standard strstr() but we ignore case in this version.
- * Based on the strstr() implementation further below.
- */
-AP_DECLARE(char *) ap_strcasestr(const char *s1, const char *s2)
-{
- char *p1, *p2;
- if (*s2 == '\0') {
- /* an empty s2 */
- return((char *)s1);
- }
- while(1) {
- for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++);
- if (*s1 == '\0') return(NULL);
- /* found first character of s2, see if the rest matches */
- p1 = (char *)s1;
- p2 = (char *)s2;
- while (apr_tolower(*++p1) == apr_tolower(*++p2)) {
- if (*p1 == '\0') {
- /* both strings ended together */
- return((char *)s1);
- }
- }
- if (*p2 == '\0') {
- /* second string ended, a match */
- break;
- }
- /* didn't find a match here, try starting at next character in s1 */
- s1++;
- }
- return((char *)s1);
-}
-
-/*
- * Returns an offsetted pointer in bigstring immediately after
- * prefix. Returns bigstring if bigstring doesn't start with
- * prefix or if prefix is longer than bigstring while still matching.
- * NOTE: pointer returned is relative to bigstring, so we
- * can use standard pointer comparisons in the calling function
- * (eg: test if ap_stripprefix(a,b) == a)
- */
-AP_DECLARE(const char *) ap_stripprefix(const char *bigstring,
- const char *prefix)
-{
- const char *p1;
-
- if (*prefix == '\0')
- return bigstring;
-
- p1 = bigstring;
- while (*p1 && *prefix) {
- if (*p1++ != *prefix++)
- return bigstring;
- }
- if (*prefix == '\0')
- return p1;
-
- /* hit the end of bigstring! */
- return bigstring;
-}
-
-/*
- * Apache stub function for the regex libraries regexec() to make sure the
- * whole regex(3) API is available through the Apache (exported) namespace.
- * This is especially important for the DSO situations of modules.
- * DO NOT MAKE A MACRO OUT OF THIS FUNCTION!
- */
-AP_DECLARE(int) ap_regexec(regex_t *preg, const char *string,
- size_t nmatch, regmatch_t pmatch[], int eflags)
-{
- return regexec(preg, string, nmatch, pmatch, eflags);
-}
-
-AP_DECLARE(size_t) ap_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
-{
- return regerror(errcode, preg, errbuf, errbuf_size);
-}
-
-
-/* This function substitutes for $0-$9, filling in regular expression
- * submatches. Pass it the same nmatch and pmatch arguments that you
- * passed ap_regexec(). pmatch should not be greater than the maximum number
- * of subexpressions - i.e. one more than the re_nsub member of regex_t.
- *
- * input should be the string with the $-expressions, source should be the
- * string that was matched against.
- *
- * It returns the substituted string, or NULL on error.
- *
- * Parts of this code are based on Henry Spencer's regsub(), from his
- * AT&T V8 regexp package.
- */
-
-AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, const char *source,
- size_t nmatch, regmatch_t pmatch[])
-{
- const char *src = input;
- char *dest, *dst;
- char c;
- size_t no;
- int len;
-
- if (!source)
- return NULL;
- if (!nmatch)
- return apr_pstrdup(p, src);
-
- /* First pass, find the size */
-
- len = 0;
-
- while ((c = *src++) != '\0') {
- if (c == '&')
- no = 0;
- else if (c == '$' && apr_isdigit(*src))
- no = *src++ - '0';
- else
- no = 10;
-
- if (no > 9) { /* Ordinary character. */
- if (c == '\\' && (*src == '$' || *src == '&'))
- c = *src++;
- len++;
- }
- else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
- len += pmatch[no].rm_eo - pmatch[no].rm_so;
- }
-
- }
-
- dest = dst = apr_pcalloc(p, len + 1);
-
- /* Now actually fill in the string */
-
- src = input;
-
- while ((c = *src++) != '\0') {
- if (c == '&')
- no = 0;
- else if (c == '$' && apr_isdigit(*src))
- no = *src++ - '0';
- else
- no = 10;
-
- if (no > 9) { /* Ordinary character. */
- if (c == '\\' && (*src == '$' || *src == '&'))
- c = *src++;
- *dst++ = c;
- }
- else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
- len = pmatch[no].rm_eo - pmatch[no].rm_so;
- memcpy(dst, source + pmatch[no].rm_so, len);
- dst += len;
- }
-
- }
- *dst = '\0';
-
- return dest;
-}
-
-/*
- * Parse .. so we don't compromise security
- */
-AP_DECLARE(void) ap_getparents(char *name)
-{
- int l, w;
-
- /* Four paseses, as per RFC 1808 */
- /* a) remove ./ path segments */
-
- for (l = 0, w = 0; name[l] != '\0';) {
- if (name[l] == '.' && name[l + 1] == '/' && (l == 0 || name[l - 1] == '/'))
- l += 2;
- else
- name[w++] = name[l++];
- }
-
- /* b) remove trailing . path, segment */
- if (w == 1 && name[0] == '.')
- w--;
- else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/')
- w--;
- name[w] = '\0';
-
- /* c) remove all xx/../ segments. (including leading ../ and /../) */
- l = 0;
-
- while (name[l] != '\0') {
- if (name[l] == '.' && name[l + 1] == '.' && name[l + 2] == '/' &&
- (l == 0 || name[l - 1] == '/')) {
- register int m = l + 3, n;
-
- l = l - 2;
- if (l >= 0) {
- while (l >= 0 && name[l] != '/')
- l--;
- l++;
- }
- else
- l = 0;
- n = l;
- while ((name[n] = name[m]))
- (++n, ++m);
- }
- else
- ++l;
- }
-
- /* d) remove trailing xx/.. segment. */
- if (l == 2 && name[0] == '.' && name[1] == '.')
- name[0] = '\0';
- else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' && name[l - 3] == '/') {
- l = l - 4;
- if (l >= 0) {
- while (l >= 0 && name[l] != '/')
- l--;
- l++;
- }
- else
- l = 0;
- name[l] = '\0';
- }
-}
-
-AP_DECLARE(void) ap_no2slash(char *name)
-{
- char *d, *s;
-
- s = d = name;
-
-#ifdef HAVE_UNC_PATHS
- /* Check for UNC names. Leave leading two slashes. */
- if (s[0] == '/' && s[1] == '/')
- *d++ = *s++;
-#endif
-
- while (*s) {
- if ((*d++ = *s) == '/') {
- do {
- ++s;
- } while (*s == '/');
- }
- else {
- ++s;
- }
- }
- *d = '\0';
-}
-
-
-/*
- * copy at most n leading directories of s into d
- * d should be at least as large as s plus 1 extra byte
- * assumes n > 0
- * the return value is the ever useful pointer to the trailing \0 of d
- *
- * MODIFIED FOR HAVE_DRIVE_LETTERS and NETWARE environments,
- * so that if n == 0, "/" is returned in d with n == 1
- * and s == "e:/test.html", "e:/" is returned in d
- * *** See also directory_walk in modules/http/http_request.c
-
- * examples:
- * /a/b, 0 ==> / (true for all platforms)
- * /a/b, 1 ==> /
- * /a/b, 2 ==> /a/
- * /a/b, 3 ==> /a/b/
- * /a/b, 4 ==> /a/b/
- *
- * c:/a/b 0 ==> /
- * c:/a/b 1 ==> c:/
- * c:/a/b 2 ==> c:/a/
- * c:/a/b 3 ==> c:/a/b
- * c:/a/b 4 ==> c:/a/b
- */
-AP_DECLARE(char *) ap_make_dirstr_prefix(char *d, const char *s, int n)
-{
- if (n < 1) {
- *d = '/';
- *++d = '\0';
- return (d);
- }
-
- for (;;) {
- if (*s == '\0' || (*s == '/' && (--n) == 0)) {
- *d = '/';
- break;
- }
- *d++ = *s++;
- }
- *++d = 0;
- return (d);
-}
-
-
-/*
- * return the parent directory name including trailing / of the file s
- */
-AP_DECLARE(char *) ap_make_dirstr_parent(apr_pool_t *p, const char *s)
-{
- const char *last_slash = ap_strrchr_c(s, '/');
- char *d;
- int l;
-
- if (last_slash == NULL) {
- /* XXX: well this is really broken if this happens */
- return (apr_pstrdup(p, "/"));
- }
- l = (last_slash - s) + 1;
- d = apr_palloc(p, l + 1);
- memcpy(d, s, l);
- d[l] = 0;
- return (d);
-}
-
-
-AP_DECLARE(int) ap_count_dirs(const char *path)
-{
- register int x, n;
-
- for (x = 0, n = 0; path[x]; x++)
- if (path[x] == '/')
- n++;
- return n;
-}
-
-AP_DECLARE(char *) ap_getword_nc(apr_pool_t *atrans, char **line, char stop)
-{
- return ap_getword(atrans, (const char **) line, stop);
-}
-
-AP_DECLARE(char *) ap_getword(apr_pool_t *atrans, const char **line, char stop)
-{
- const char *pos = ap_strchr_c(*line, stop);
- char *res;
-
- if (!pos) {
- res = apr_pstrdup(atrans, *line);
- *line += strlen(*line);
- return res;
- }
-
- res = apr_pstrndup(atrans, *line, pos - *line);
-
- while (*pos == stop) {
- ++pos;
- }
-
- *line = pos;
-
- return res;
-}
-
-AP_DECLARE(char *) ap_getword_white_nc(apr_pool_t *atrans, char **line)
-{
- return ap_getword_white(atrans, (const char **) line);
-}
-
-AP_DECLARE(char *) ap_getword_white(apr_pool_t *atrans, const char **line)
-{
- int pos = -1, x;
- char *res;
-
- for (x = 0; (*line)[x]; x++) {
- if (apr_isspace((*line)[x])) {
- pos = x;
- break;
- }
- }
-
- if (pos == -1) {
- res = apr_pstrdup(atrans, *line);
- *line += strlen(*line);
- return res;
- }
-
- res = apr_palloc(atrans, pos + 1);
- apr_cpystrn(res, *line, pos + 1);
-
- while (apr_isspace((*line)[pos]))
- ++pos;
-
- *line += pos;
-
- return res;
-}
-
-AP_DECLARE(char *) ap_getword_nulls_nc(apr_pool_t *atrans, char **line, char stop)
-{
- return ap_getword_nulls(atrans, (const char **) line, stop);
-}
-
-AP_DECLARE(char *) ap_getword_nulls(apr_pool_t *atrans, const char **line, char stop)
-{
- const char *pos = ap_strchr_c(*line, stop);
- char *res;
-
- if (!pos) {
- res = apr_pstrdup(atrans, *line);
- *line += strlen(*line);
- return res;
- }
-
- res = apr_pstrndup(atrans, *line, pos - *line);
-
- ++pos;
-
- *line = pos;
-
- return res;
-}
-
-/* Get a word, (new) config-file style --- quoted strings and backslashes
- * all honored
- */
-
-static char *substring_conf(apr_pool_t *p, const char *start, int len, char quote)
-{
- char *result = apr_palloc(p, len + 2);
- char *resp = result;
- int i;
-
- for (i = 0; i < len; ++i) {
- if (start[i] == '\\' && (start[i + 1] == '\\'
- || (quote && start[i + 1] == quote)))
- *resp++ = start[++i];
- else
- *resp++ = start[i];
- }
-
- *resp++ = '\0';
-#if RESOLVE_ENV_PER_TOKEN
- return ap_resolve_env(p,result);
-#else
- return result;
-#endif
-}
-
-AP_DECLARE(char *) ap_getword_conf_nc(apr_pool_t *p, char **line)
-{
- return ap_getword_conf(p, (const char **) line);
-}
-
-AP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line)
-{
- const char *str = *line, *strend;
- char *res;
- char quote;
-
- while (*str && apr_isspace(*str))
- ++str;
-
- if (!*str) {
- *line = str;
- return "";
- }
-
- if ((quote = *str) == '"' || quote == '\'') {
- strend = str + 1;
- while (*strend && *strend != quote) {
- if (*strend == '\\' && strend[1] && strend[1] == quote)
- strend += 2;
- else
- ++strend;
- }
- res = substring_conf(p, str + 1, strend - str - 1, quote);
-
- if (*strend == quote)
- ++strend;
- }
- else {
- strend = str;
- while (*strend && !apr_isspace(*strend))
- ++strend;
-
- res = substring_conf(p, str, strend - str, 0);
- }
-
- while (*strend && apr_isspace(*strend))
- ++strend;
- *line = strend;
- return res;
-}
-
-/* Check a string for any ${ENV} environment variable
- * construct and replace each them by the value of
- * that environment variable, if it exists. If the
- * environment value does not exist, leave the ${ENV}
- * construct alone; it means something else.
- */
-AP_DECLARE(const char *) ap_resolve_env(apr_pool_t *p, const char * word)
-{
- char tmp[ MAX_STRING_LEN ];
- const char *s, *e;
- tmp[0] = '\0';
-
- if (!(s=ap_strchr_c(word,'$')))
- return word;
-
- do {
- /* XXX - relies on strncat() to add '\0'
- */
- strncat(tmp,word,s - word);
- if ((s[1] == '{') && (e=ap_strchr_c(s,'}'))) {
- const char *e2 = e;
- word = e + 1;
- e = getenv(s+2);
- if (e) {
- strcat(tmp,e);
- } else {
- strncat(tmp, s, e2-s);
- strcat(tmp,"}");
- }
- } else {
- /* ignore invalid strings */
- word = s+1;
- strcat(tmp,"$");
- };
- } while ((s=ap_strchr_c(word,'$')));
- strcat(tmp,word);
-
- return apr_pstrdup(p,tmp);
-}
-AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp)
-{
-#ifdef DEBUG
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
- "Done with config file %s", cfp->name);
-#endif
- return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
-}
-
-static apr_status_t cfg_close(void *param)
-{
- apr_file_t *cfp = (apr_file_t *) param;
- return (apr_file_close(cfp));
-}
-
-static int cfg_getch(void *param)
-{
- char ch;
- apr_file_t *cfp = (apr_file_t *) param;
- if (apr_file_getc(&ch, cfp) == APR_SUCCESS)
- return ch;
- return (int)EOF;
-}
-
-static void *cfg_getstr(void *buf, size_t bufsiz, void *param)
-{
- apr_file_t *cfp = (apr_file_t *) param;
- apr_status_t rv;
- rv = apr_file_gets(buf, bufsiz, cfp);
- if (rv == APR_SUCCESS || (rv == APR_EOF && strcmp(buf, "")))
- return buf;
- return NULL;
-}
-
-/* Open a ap_configfile_t as FILE, return open ap_configfile_t struct pointer */
-AP_DECLARE(apr_status_t) ap_pcfg_openfile(ap_configfile_t **ret_cfg, apr_pool_t *p, const char *name)
-{
- ap_configfile_t *new_cfg;
- apr_file_t *file = NULL;
- apr_finfo_t finfo;
- apr_status_t status;
-#ifdef DEBUG
- char buf[120];
-#endif
-
- if (name == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
- "Internal error: pcfg_openfile() called with NULL filename");
- return APR_EBADF;
- }
-
- /* ### We no longer need the test ap_os_is_filename_valid() here
- * The directory was already walked on a segment by segment basis,
- * so we should never be called with a bad path element, and device
- * names as access file names never posed as security threats, since
- * it was the admin's choice to assign the .htaccess file's name.
- */
-
- status = apr_file_open(&file, name, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, p);
-#ifdef DEBUG
- ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, NULL,
- "Opening config file %s (%s)",
- name, (status != APR_SUCCESS) ?
- apr_strerror(status, buf, sizeof(buf)) : "successful");
-#endif
- if (status != APR_SUCCESS)
- return status;
-
- status = apr_file_info_get(&finfo, APR_FINFO_TYPE, file);
- if (status != APR_SUCCESS)
- return status;
-
- if (finfo.filetype != APR_REG &&
-#if defined(WIN32) || defined(OS2)
- !(strcasecmp(name, "nul") == 0 ||
- (strlen(name) >= 4 &&
- strcasecmp(name + strlen(name) - 4, "/nul") == 0))) {
-#else
- strcmp(name, "/dev/null") != 0) {
-#endif /* WIN32 || OS2 */
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
- "Access to file %s denied by server: not a regular file",
- name);
- apr_file_close(file);
- return APR_EBADF;
- }
-
- new_cfg = apr_palloc(p, sizeof(*new_cfg));
- new_cfg->param = file;
- new_cfg->name = apr_pstrdup(p, name);
- new_cfg->getch = (int (*)(void *)) cfg_getch;
- new_cfg->getstr = (void *(*)(void *, size_t, void *)) cfg_getstr;
- new_cfg->close = (int (*)(void *)) cfg_close;
- new_cfg->line_number = 0;
- *ret_cfg = new_cfg;
- return APR_SUCCESS;
-}
-
-
-/* Allocate a ap_configfile_t handle with user defined functions and params */
-AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(apr_pool_t *p, const char *descr,
- void *param,
- int(*getch)(void *param),
- void *(*getstr) (void *buf, size_t bufsiz, void *param),
- int(*close_func)(void *param))
-{
- ap_configfile_t *new_cfg = apr_palloc(p, sizeof(*new_cfg));
-#ifdef DEBUG
- ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, NULL, "Opening config handler %s", descr);
-#endif
- new_cfg->param = param;
- new_cfg->name = descr;
- new_cfg->getch = getch;
- new_cfg->getstr = getstr;
- new_cfg->close = close_func;
- new_cfg->line_number = 0;
- return new_cfg;
-}
-
-/* Read one character from a configfile_t */
-AP_DECLARE(int) ap_cfg_getc(ap_configfile_t *cfp)
-{
- register int ch = cfp->getch(cfp->param);
- if (ch == LF)
- ++cfp->line_number;
- return ch;
-}
-
-/* Read one line from open ap_configfile_t, strip LF, increase line number */
-/* If custom handler does not define a getstr() function, read char by char */
-AP_DECLARE(int) ap_cfg_getline(char *buf, size_t bufsize, ap_configfile_t *cfp)
-{
- /* If a "get string" function is defined, use it */
- if (cfp->getstr != NULL) {
- char *src, *dst;
- char *cp;
- char *cbuf = buf;
- size_t cbufsize = bufsize;
-
- while (1) {
- ++cfp->line_number;
- if (cfp->getstr(cbuf, cbufsize, cfp->param) == NULL)
- return 1;
-
- /*
- * check for line continuation,
- * i.e. match [^\\]\\[\r]\n only
- */
- cp = cbuf;
- while (cp < cbuf+cbufsize && *cp != '\0')
- cp++;
- if (cp > cbuf && cp[-1] == LF) {
- cp--;
- if (cp > cbuf && cp[-1] == CR)
- cp--;
- if (cp > cbuf && cp[-1] == '\\') {
- cp--;
- if (!(cp > cbuf && cp[-1] == '\\')) {
- /*
- * line continuation requested -
- * then remove backslash and continue
- */
- cbufsize -= (cp-cbuf);
- cbuf = cp;
- continue;
- }
- else {
- /*
- * no real continuation because escaped -
- * then just remove escape character
- */
- for ( ; cp < cbuf+cbufsize && *cp != '\0'; cp++)
- cp[0] = cp[1];
- }
- }
- }
- break;
- }
-
- /*
- * Leading and trailing white space is eliminated completely
- */
- src = buf;
- while (apr_isspace(*src))
- ++src;
- /* blast trailing whitespace */
- dst = &src[strlen(src)];
- while (--dst >= src && apr_isspace(*dst))
- *dst = '\0';
- /* Zap leading whitespace by shifting */
- if (src != buf)
- for (dst = buf; (*dst++ = *src++) != '\0'; )
- ;
-
-#ifdef DEBUG_CFG_LINES
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "Read config: %s", buf);
-#endif
- return 0;
- } else {
- /* No "get string" function defined; read character by character */
- register int c;
- register size_t i = 0;
-
- buf[0] = '\0';
- /* skip leading whitespace */
- do {
- c = cfp->getch(cfp->param);
- } while (c == '\t' || c == ' ');
-
- if (c == EOF)
- return 1;
-
- if(bufsize < 2) {
- /* too small, assume caller is crazy */
- return 1;
- }
-
- while (1) {
- if ((c == '\t') || (c == ' ')) {
- buf[i++] = ' ';
- while ((c == '\t') || (c == ' '))
- c = cfp->getch(cfp->param);
- }
- if (c == CR) {
- /* silently ignore CR (_assume_ that a LF follows) */
- c = cfp->getch(cfp->param);
- }
- if (c == LF) {
- /* increase line number and return on LF */
- ++cfp->line_number;
- }
- if (c == EOF || c == 0x4 || c == LF || i >= (bufsize - 2)) {
- /*
- * check for line continuation
- */
- if (i > 0 && buf[i-1] == '\\') {
- i--;
- if (!(i > 0 && buf[i-1] == '\\')) {
- /* line is continued */
- c = cfp->getch(cfp->param);
- continue;
- }
- /* else nothing needs be done because
- * then the backslash is escaped and
- * we just strip to a single one
- */
- }
- /* blast trailing whitespace */
- while (i > 0 && apr_isspace(buf[i - 1]))
- --i;
- buf[i] = '\0';
-#ifdef DEBUG_CFG_LINES
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "Read config: %s", buf);
-#endif
- return 0;
- }
- buf[i] = c;
- ++i;
- c = cfp->getch(cfp->param);
- }
- }
-}
-
-/* Size an HTTP header field list item, as separated by a comma.
- * The return value is a pointer to the beginning of the non-empty list item
- * within the original string (or NULL if there is none) and the address
- * of field is shifted to the next non-comma, non-whitespace character.
- * len is the length of the item excluding any beginning whitespace.
- */
-AP_DECLARE(const char *) ap_size_list_item(const char **field, int *len)
-{
- const unsigned char *ptr = (const unsigned char *)*field;
- const unsigned char *token;
- int in_qpair, in_qstr, in_com;
-
- /* Find first non-comma, non-whitespace byte */
-
- while (*ptr == ',' || apr_isspace(*ptr))
- ++ptr;
-
- token = ptr;
-
- /* Find the end of this item, skipping over dead bits */
-
- for (in_qpair = in_qstr = in_com = 0;
- *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
- ++ptr) {
-
- if (in_qpair) {
- in_qpair = 0;
- }
- else {
- switch (*ptr) {
- case '\\': in_qpair = 1; /* quoted-pair */
- break;
- case '"' : if (!in_com) /* quoted string delim */
- in_qstr = !in_qstr;
- break;
- case '(' : if (!in_qstr) /* comment (may nest) */
- ++in_com;
- break;
- case ')' : if (in_com) /* end comment */
- --in_com;
- break;
- default : break;
- }
- }
- }
-
- if ((*len = (ptr - token)) == 0) {
- *field = (const char *)ptr;
- return NULL;
- }
-
- /* Advance field pointer to the next non-comma, non-white byte */
-
- while (*ptr == ',' || apr_isspace(*ptr))
- ++ptr;
-
- *field = (const char *)ptr;
- return (const char *)token;
-}
-
-/* Retrieve an HTTP header field list item, as separated by a comma,
- * while stripping insignificant whitespace and lowercasing anything not in
- * a quoted string or comment. The return value is a new string containing
- * the converted list item (or NULL if none) and the address pointed to by
- * field is shifted to the next non-comma, non-whitespace.
- */
-AP_DECLARE(char *) ap_get_list_item(apr_pool_t *p, const char **field)
-{
- const char *tok_start;
- const unsigned char *ptr;
- unsigned char *pos;
- char *token;
- int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;
-
- /* Find the beginning and maximum length of the list item so that
- * we can allocate a buffer for the new string and reset the field.
- */
- if ((tok_start = ap_size_list_item(field, &tok_len)) == NULL) {
- return NULL;
- }
- token = apr_palloc(p, tok_len + 1);
-
- /* Scan the token again, but this time copy only the good bytes.
- * We skip extra whitespace and any whitespace around a '=', '/',
- * or ';' and lowercase normal characters not within a comment,
- * quoted-string or quoted-pair.
- */
- for (ptr = (const unsigned char *)tok_start, pos = (unsigned char *)token;
- *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
- ++ptr) {
-
- if (in_qpair) {
- in_qpair = 0;
- *pos++ = *ptr;
- }
- else {
- switch (*ptr) {
- case '\\': in_qpair = 1;
- if (addspace == 1)
- *pos++ = ' ';
- *pos++ = *ptr;
- addspace = 0;
- break;
- case '"' : if (!in_com)
- in_qstr = !in_qstr;
- if (addspace == 1)
- *pos++ = ' ';
- *pos++ = *ptr;
- addspace = 0;
- break;
- case '(' : if (!in_qstr)
- ++in_com;
- if (addspace == 1)
- *pos++ = ' ';
- *pos++ = *ptr;
- addspace = 0;
- break;
- case ')' : if (in_com)
- --in_com;
- *pos++ = *ptr;
- addspace = 0;
- break;
- case ' ' :
- case '\t': if (addspace)
- break;
- if (in_com || in_qstr)
- *pos++ = *ptr;
- else
- addspace = 1;
- break;
- case '=' :
- case '/' :
- case ';' : if (!(in_com || in_qstr))
- addspace = -1;
- *pos++ = *ptr;
- break;
- default : if (addspace == 1)
- *pos++ = ' ';
- *pos++ = (in_com || in_qstr) ? *ptr
- : apr_tolower(*ptr);
- addspace = 0;
- break;
- }
- }
- }
- *pos = '\0';
-
- return token;
-}
-
-/* Find an item in canonical form (lowercase, no extra spaces) within
- * an HTTP field value list. Returns 1 if found, 0 if not found.
- * This would be much more efficient if we stored header fields as
- * an array of list items as they are received instead of a plain string.
- */
-AP_DECLARE(int) ap_find_list_item(apr_pool_t *p, const char *line, const char *tok)
-{
- const unsigned char *pos;
- const unsigned char *ptr = (const unsigned char *)line;
- int good = 0, addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0;
-
- if (!line || !tok)
- return 0;
-
- do { /* loop for each item in line's list */
-
- /* Find first non-comma, non-whitespace byte */
-
- while (*ptr == ',' || apr_isspace(*ptr))
- ++ptr;
-
- if (*ptr)
- good = 1; /* until proven otherwise for this item */
- else
- break; /* no items left and nothing good found */
-
- /* We skip extra whitespace and any whitespace around a '=', '/',
- * or ';' and lowercase normal characters not within a comment,
- * quoted-string or quoted-pair.
- */
- for (pos = (const unsigned char *)tok;
- *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
- ++ptr) {
-
- if (in_qpair) {
- in_qpair = 0;
- if (good)
- good = (*pos++ == *ptr);
- }
- else {
- switch (*ptr) {
- case '\\': in_qpair = 1;
- if (addspace == 1)
- good = good && (*pos++ == ' ');
- good = good && (*pos++ == *ptr);
- addspace = 0;
- break;
- case '"' : if (!in_com)
- in_qstr = !in_qstr;
- if (addspace == 1)
- good = good && (*pos++ == ' ');
- good = good && (*pos++ == *ptr);
- addspace = 0;
- break;
- case '(' : if (!in_qstr)
- ++in_com;
- if (addspace == 1)
- good = good && (*pos++ == ' ');
- good = good && (*pos++ == *ptr);
- addspace = 0;
- break;
- case ')' : if (in_com)
- --in_com;
- good = good && (*pos++ == *ptr);
- addspace = 0;
- break;
- case ' ' :
- case '\t': if (addspace || !good)
- break;
- if (in_com || in_qstr)
- good = (*pos++ == *ptr);
- else
- addspace = 1;
- break;
- case '=' :
- case '/' :
- case ';' : if (!(in_com || in_qstr))
- addspace = -1;
- good = good && (*pos++ == *ptr);
- break;
- default : if (!good)
- break;
- if (addspace == 1)
- good = (*pos++ == ' ');
- if (in_com || in_qstr)
- good = good && (*pos++ == *ptr);
- else
- good = good && (*pos++ == apr_tolower(*ptr));
- addspace = 0;
- break;
- }
- }
- }
- if (good && *pos)
- good = 0; /* not good if only a prefix was matched */
-
- } while (*ptr && !good);
-
- return good;
-}
-
-
-/* Retrieve a token, spacing over it and returning a pointer to
- * the first non-white byte afterwards. Note that these tokens
- * are delimited by semis and commas; and can also be delimited
- * by whitespace at the caller's option.
- */
-
-AP_DECLARE(char *) ap_get_token(apr_pool_t *p, const char **accept_line, int accept_white)
-{
- const char *ptr = *accept_line;
- const char *tok_start;
- char *token;
- int tok_len;
-
- /* Find first non-white byte */
-
- while (*ptr && apr_isspace(*ptr))
- ++ptr;
-
- tok_start = ptr;
-
- /* find token end, skipping over quoted strings.
- * (comments are already gone).
- */
-
- while (*ptr && (accept_white || !apr_isspace(*ptr))
- && *ptr != ';' && *ptr != ',') {
- if (*ptr++ == '"')
- while (*ptr)
- if (*ptr++ == '"')
- break;
- }
-
- tok_len = ptr - tok_start;
- token = apr_pstrndup(p, tok_start, tok_len);
-
- /* Advance accept_line pointer to the next non-white byte */
-
- while (*ptr && apr_isspace(*ptr))
- ++ptr;
-
- *accept_line = ptr;
- return token;
-}
-
-
-/* find http tokens, see the definition of token from RFC2068 */
-AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok)
-{
- const unsigned char *start_token;
- const unsigned char *s;
-
- if (!line)
- return 0;
-
- s = (const unsigned char *)line;
- for (;;) {
- /* find start of token, skip all stop characters, note NUL
- * isn't a token stop, so we don't need to test for it
- */
- while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
- ++s;
- }
- if (!*s) {
- return 0;
- }
- start_token = s;
- /* find end of the token */
- while (*s && !TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
- ++s;
- }
- if (!strncasecmp((const char *)start_token, (const char *)tok, s - start_token)) {
- return 1;
- }
- if (!*s) {
- return 0;
- }
- }
-}
-
-
-AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line, const char *tok)
-{
- int llen, tlen, lidx;
-
- if (!line)
- return 0;
-
- llen = strlen(line);
- tlen = strlen(tok);
- lidx = llen - tlen;
-
- if ((lidx < 0) ||
- ((lidx > 0) && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))
- return 0;
-
- return (strncasecmp(&line[lidx], tok, tlen) == 0);
-}
-
-AP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str)
-{
- char *cmd;
- unsigned char *d;
- const unsigned char *s;
-
- cmd = apr_palloc(p, 2 * strlen(str) + 1); /* Be safe */
- d = (unsigned char *)cmd;
- s = (const unsigned char *)str;
- for (; *s; ++s) {
-
-#if defined(OS2) || defined(WIN32)
- /* Don't allow '&' in parameters under OS/2. */
- /* This can be used to send commands to the shell. */
- if (*s == '&') {
- *d++ = ' ';
- continue;
- }
-#endif
-
- if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
- *d++ = '\\';
- }
- *d++ = *s;
- }
- *d = '\0';
-
- return cmd;
-}
-
-static char x2c(const char *what)
-{
- register char digit;
-
-#if !APR_CHARSET_EBCDIC
- digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
- digit *= 16;
- digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0'));
-#else /*APR_CHARSET_EBCDIC*/
- char xstr[5];
- xstr[0]='0';
- xstr[1]='x';
- xstr[2]=what[0];
- xstr[3]=what[1];
- xstr[4]='\0';
- digit = apr_xlate_conv_byte(ap_hdrs_from_ascii, 0xFF & strtol(xstr, NULL, 16));
-#endif /*APR_CHARSET_EBCDIC*/
- return (digit);
-}
-
-/*
- * Unescapes a URL.
- * Returns 0 on success, non-zero on error
- * Failure is due to
- * bad % escape returns HTTP_BAD_REQUEST
- *
- * decoding %00 -> \0
- * decoding %2f -> / (a special character)
- * returns HTTP_NOT_FOUND
- */
-AP_DECLARE(int) ap_unescape_url(char *url)
-{
- register int badesc, badpath;
- char *x, *y;
-
- badesc = 0;
- badpath = 0;
- /* Initial scan for first '%'. Don't bother writing values before
- * seeing a '%' */
- y = strchr(url, '%');
- if (y == NULL) {
- return OK;
- }
- for (x = y; *y; ++x, ++y) {
- if (*y != '%')
- *x = *y;
- else {
- if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {
- badesc = 1;
- *x = '%';
- }
- else {
- *x = x2c(y + 1);
- y += 2;
- if (*x == '/' || *x == '\0')
- badpath = 1;
- }
- }
- }
- *x = '\0';
- if (badesc)
- return HTTP_BAD_REQUEST;
- else if (badpath)
- return HTTP_NOT_FOUND;
- else
- return OK;
-}
-
-AP_DECLARE(char *) ap_construct_server(apr_pool_t *p, const char *hostname,
- apr_port_t port, const request_rec *r)
-{
- if (ap_is_default_port(port, r))
- return apr_pstrdup(p, hostname);
- else {
- return apr_psprintf(p, "%s:%u", hostname, port);
- }
-}
-
-/* c2x takes an unsigned, and expects the caller has guaranteed that
- * 0 <= what < 256... which usually means that you have to cast to
- * unsigned char first, because (unsigned)(char)(x) first goes through
- * signed extension to an int before the unsigned cast.
- *
- * The reason for this assumption is to assist gcc code generation --
- * the unsigned char -> unsigned extension is already done earlier in
- * both uses of this code, so there's no need to waste time doing it
- * again.
- */
-static const char c2x_table[] = "0123456789abcdef";
-
-static APR_INLINE unsigned char *c2x(unsigned what, unsigned char *where)
-{
-#if APR_CHARSET_EBCDIC
- what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what);
-#endif /*APR_CHARSET_EBCDIC*/
- *where++ = '%';
- *where++ = c2x_table[what >> 4];
- *where++ = c2x_table[what & 0xf];
- return where;
-}
-
-/*
- * escape_path_segment() escapes a path segment, as defined in RFC 1808. This
- * routine is (should be) OS independent.
- *
- * os_escape_path() converts an OS path to a URL, in an OS dependent way. In all
- * cases if a ':' occurs before the first '/' in the URL, the URL should be
- * prefixed with "./" (or the ':' escaped). In the case of Unix, this means
- * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
- * efficiency reasons, we don't use escape_path_segment(), which is provided for
- * reference. Again, RFC 1808 is where this stuff is defined.
- *
- * If partial is set, os_escape_path() assumes that the path will be appended to
- * something with a '/' in it (and thus does not prefix "./").
- */
-
-AP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *segment)
-{
- char *copy = apr_palloc(p, 3 * strlen(segment) + 1);
- const unsigned char *s = (const unsigned char *)segment;
- unsigned char *d = (unsigned char *)copy;
- unsigned c;
-
- while ((c = *s)) {
- if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
- d = c2x(c, d);
- }
- else {
- *d++ = c;
- }
- ++s;
- }
- *d = '\0';
- return copy;
-}
-
-AP_DECLARE(char *) ap_os_escape_path(apr_pool_t *p, const char *path, int partial)
-{
- char *copy = apr_palloc(p, 3 * strlen(path) + 3);
- const unsigned char *s = (const unsigned char *)path;
- unsigned char *d = (unsigned char *)copy;
- unsigned c;
-
- if (!partial) {
- const char *colon = ap_strchr_c(path, ':');
- const char *slash = ap_strchr_c(path, '/');
-
- if (colon && (!slash || colon < slash)) {
- *d++ = '.';
- *d++ = '/';
- }
- }
- while ((c = *s)) {
- if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
- d = c2x(c, d);
- }
- else {
- *d++ = c;
- }
- ++s;
- }
- *d = '\0';
- return copy;
-}
-
-/* ap_escape_uri is now a macro for os_escape_path */
-
-AP_DECLARE(char *) ap_escape_html(apr_pool_t *p, const char *s)
-{
- int i, j;
- char *x;
-
- /* first, count the number of extra characters */
- for (i = 0, j = 0; s[i] != '\0'; i++)
- if (s[i] == '<' || s[i] == '>')
- j += 3;
- else if (s[i] == '&')
- j += 4;
-
- if (j == 0)
- return apr_pstrndup(p, s, i);
-
- x = apr_palloc(p, i + j + 1);
- for (i = 0, j = 0; s[i] != '\0'; i++, j++)
- if (s[i] == '<') {
- memcpy(&x[j], "&lt;", 4);
- j += 3;
- }
- else if (s[i] == '>') {
- memcpy(&x[j], "&gt;", 4);
- j += 3;
- }
- else if (s[i] == '&') {
- memcpy(&x[j], "&amp;", 5);
- j += 4;
- }
- else
- x[j] = s[i];
-
- x[j] = '\0';
- return x;
-}
-
-AP_DECLARE(int) ap_is_directory(apr_pool_t *p, const char *path)
-{
- apr_finfo_t finfo;
-
- if (apr_stat(&finfo, path, APR_FINFO_TYPE, p) != APR_SUCCESS)
- return 0; /* in error condition, just return no */
-
- return (finfo.filetype == APR_DIR);
-}
-
-AP_DECLARE(int) ap_is_rdirectory(apr_pool_t *p, const char *path)
-{
- apr_finfo_t finfo;
-
- if (apr_lstat(&finfo, path, APR_FINFO_TYPE, p) != APR_SUCCESS)
- return 0; /* in error condition, just return no */
-
- return (finfo.filetype == APR_DIR);
-}
-
-AP_DECLARE(char *) ap_make_full_path(apr_pool_t *a, const char *src1,
- const char *src2)
-{
- register int x;
-
- x = strlen(src1);
- if (x == 0)
- return apr_pstrcat(a, "/", src2, NULL);
-
- if (src1[x - 1] != '/')
- return apr_pstrcat(a, src1, "/", src2, NULL);
- else
- return apr_pstrcat(a, src1, src2, NULL);
-}
-
-/*
- * Check for an absoluteURI syntax (see section 3.2 in RFC2068).
- */
-AP_DECLARE(int) ap_is_url(const char *u)
-{
- register int x;
-
- for (x = 0; u[x] != ':'; x++) {
- if ((!u[x]) ||
- ((!apr_isalpha(u[x])) && (!apr_isdigit(u[x])) &&
- (u[x] != '+') && (u[x] != '-') && (u[x] != '.'))) {
- return 0;
- }
- }
-
- return (x ? 1 : 0); /* If the first character is ':', it's broken, too */
-}
-
-AP_DECLARE(int) ap_ind(const char *s, char c)
-{
- const char *p = ap_strchr_c(s, c);
-
- if (p == NULL)
- return -1;
- return p - s;
-}
-
-AP_DECLARE(int) ap_rind(const char *s, char c)
-{
- const char *p = ap_strrchr_c(s, c);
-
- if (p == NULL)
- return -1;
- return p - s;
-}
-
-AP_DECLARE(void) ap_str_tolower(char *str)
-{
- while (*str) {
- *str = apr_tolower(*str);
- ++str;
- }
-}
-
-static char *find_fqdn(apr_pool_t *a, struct hostent *p)
-{
- int x;
-
- if (!strchr(p->h_name, '.')) {
- for (x = 0; p->h_aliases[x]; ++x) {
- if (strchr(p->h_aliases[x], '.') &&
- (!strncasecmp(p->h_aliases[x], p->h_name, strlen(p->h_name))))
- return apr_pstrdup(a, p->h_aliases[x]);
- }
- return NULL;
- }
- return apr_pstrdup(a, (void *) p->h_name);
-}
-
-char *ap_get_local_host(apr_pool_t *a)
-{
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
-#endif
- char str[MAXHOSTNAMELEN + 1];
- char *server_hostname = NULL;
- struct hostent *p;
-
-#ifdef BEOS_R5
- if (gethostname(str, sizeof(str) - 1) == 0)
-#else
- if (gethostname(str, sizeof(str) - 1) != 0)
-#endif
- {
- ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_WARNING, 0, a,
- "%s: gethostname() failed to determine ServerName",
- ap_server_argv0);
- }
- else
- {
- str[sizeof(str) - 1] = '\0';
- if ((!(p = gethostbyname(str)))
- || (!(server_hostname = find_fqdn(a, p)))) {
- /* Recovery - return the default servername by IP: */
- if (p && p->h_addr_list[0]) {
- apr_snprintf(str, sizeof(str), "%pA", p->h_addr_list[0]);
- server_hostname = apr_pstrdup(a, str);
- /* We will drop through to report the IP-named server */
- }
- }
- else {
- /* Since we found a fdqn, return it with no logged message. */
- return server_hostname;
- }
- }
-
- if (!server_hostname)
- server_hostname = apr_pstrdup(a, "127.0.0.1");
-
- ap_log_perror(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO|APLOG_STARTUP, 0, a,
- "%s: Could not determine the server's fully qualified "
- "domain name, using %s for ServerName",
- ap_server_argv0, server_hostname);
-
- return server_hostname;
-}
-
-/* simple 'pool' alloc()ing glue to apr_base64.c
- */
-AP_DECLARE(char *) ap_pbase64decode(apr_pool_t *p, const char *bufcoded)
-{
- char *decoded;
- int l;
-
- decoded = (char *) apr_palloc(p, 1 + apr_base64_decode_len(bufcoded));
- l = apr_base64_decode(decoded, bufcoded);
- decoded[l] = '\0'; /* make binary sequence into string */
-
- return decoded;
-}
-
-AP_DECLARE(char *) ap_pbase64encode(apr_pool_t *p, char *string)
-{
- char *encoded;
- int l = strlen(string);
-
- encoded = (char *) apr_palloc(p, 1 + apr_base64_encode_len(l));
- l = apr_base64_encode(encoded, string, l);
- encoded[l] = '\0'; /* make binary sequence into string */
-
- return encoded;
-}
-
-/* we want to downcase the type/subtype for comparison purposes
- * but nothing else because ;parameter=foo values are case sensitive.
- * XXX: in truth we want to downcase parameter names... but really,
- * apache has never handled parameters and such correctly. You
- * also need to compress spaces and such to be able to compare
- * properly. -djg
- */
-AP_DECLARE(void) ap_content_type_tolower(char *str)
-{
- char *semi;
-
- semi = strchr(str, ';');
- if (semi) {
- *semi = '\0';
- }
- while (*str) {
- *str = apr_tolower(*str);
- ++str;
- }
- if (semi) {
- *semi = ';';
- }
-}
-
-/*
- * Given a string, replace any bare " with \" .
- */
-AP_DECLARE(char *) ap_escape_quotes (apr_pool_t *p, const char *instring)
-{
- int newlen = 0;
- const char *inchr = instring;
- char *outchr, *outstring;
-
- /*
- * Look through the input string, jogging the length of the output
- * string up by an extra byte each time we find an unescaped ".
- */
- while (*inchr != '\0') {
- newlen++;
- if (*inchr == '"') {
- newlen++;
- }
- /*
- * If we find a slosh, and it's not the last byte in the string,
- * it's escaping something - advance past both bytes.
- */
- if ((*inchr == '\\') && (inchr[1] != '\0')) {
- inchr++;
- newlen++;
- }
- inchr++;
- }
- outstring = apr_palloc(p, newlen + 1);
- inchr = instring;
- outchr = outstring;
- /*
- * Now copy the input string to the output string, inserting a slosh
- * in front of every " that doesn't already have one.
- */
- while (*inchr != '\0') {
- if ((*inchr == '\\') && (inchr[1] != '\0')) {
- *outchr++ = *inchr++;
- *outchr++ = *inchr++;
- }
- if (*inchr == '"') {
- *outchr++ = '\\';
- }
- if (*inchr != '\0') {
- *outchr++ = *inchr++;
- }
- }
- *outchr = '\0';
- return outstring;
-}
diff --git a/server/util_cfgtree.c b/server/util_cfgtree.c
deleted file mode 100644
index b8fcad6c9c..0000000000
--- a/server/util_cfgtree.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#define CORE_PRIVATE
-#include "util_cfgtree.h"
-#include <stdlib.h>
-
-ap_directive_t *ap_add_node(ap_directive_t **parent, ap_directive_t *current,
- ap_directive_t *toadd, int child)
-{
- if (current == NULL) {
- /* we just started a new parent */
- if (*parent != NULL) {
- (*parent)->first_child = toadd;
- toadd->parent = *parent;
- }
- if (child) {
- /* First item in config file or container is a container */
- *parent = toadd;
- return NULL;
- }
- return toadd;
- }
- current->next = toadd;
- toadd->parent = *parent;
- if (child) {
- /* switch parents, navigate into child */
- *parent = toadd;
- return NULL;
- }
- return toadd;
-}
-
-
diff --git a/server/util_charset.c b/server/util_charset.c
deleted file mode 100644
index f1833b94d6..0000000000
--- a/server/util_charset.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "ap_config.h"
-
-#ifdef APACHE_XLATE
-
-#include "httpd.h"
-#include "http_log.h"
-#include "http_core.h"
-#include "util_charset.h"
-
-/* ap_hdrs_to_ascii, ap_hdrs_from_ascii
- *
- * These are the translation handles used to translate between the network
- * format of protocol headers and the local machine format.
- *
- * For an EBCDIC machine, these are valid handles which are set up at
- * initialization to translate between ISO-8859-1 and the code page of
- * the source code.
- *
- * For an ASCII machine, these remain NULL so that when they are stored
- * in the BUFF via ap_bsetop(BO_RXLATE) it ensures that no translation is
- * performed.
- */
-
-apr_xlate_t *ap_hdrs_to_ascii, *ap_hdrs_from_ascii;
-
-/* ap_locale_to_ascii, ap_locale_from_ascii
- *
- * These handles are used for the translation of content, unless a
- * configuration module overrides them.
- *
- * For an EBCDIC machine, these are valid handles which are set up at
- * initialization to translate between ISO-8859-1 and the code page of
- * the httpd process's locale.
- *
- * For an ASCII machine, these remain NULL so that no translation is
- * performed (unless a configuration module does something, of course).
- */
-
-apr_xlate_t *ap_locale_to_ascii, *ap_locale_from_ascii;
-
-#endif /*APACHE_XLATE*/
diff --git a/server/util_date.c b/server/util_date.c
deleted file mode 100644
index 89ceaa5d8d..0000000000
--- a/server/util_date.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * util_date.c: date parsing utility routines
- * These routines are (hopefully) platform independent.
- *
- * 27 Oct 1996 Roy Fielding
- * Extracted (with many modifications) from mod_proxy.c and
- * tested with over 50,000 randomly chosen valid date strings
- * and several hundred variations of invalid date strings.
- *
- */
-
-#include "apr.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "util_date.h"
-
-/*
- * Compare a string to a mask
- * Mask characters (arbitrary maximum is 256 characters, just in case):
- * @ - uppercase letter
- * $ - lowercase letter
- * & - hex digit
- * # - digit
- * ~ - digit or space
- * * - swallow remaining characters
- * <x> - exact match for any other character
- */
-AP_DECLARE(int) ap_checkmask(const char *data, const char *mask)
-{
- int i;
- char d;
-
- for (i = 0; i < 256; i++) {
- d = data[i];
- switch (mask[i]) {
- case '\0':
- return (d == '\0');
-
- case '*':
- return 1;
-
- case '@':
- if (!apr_isupper(d))
- return 0;
- break;
- case '$':
- if (!apr_islower(d))
- return 0;
- break;
- case '#':
- if (!apr_isdigit(d))
- return 0;
- break;
- case '&':
- if (!apr_isxdigit(d))
- return 0;
- break;
- case '~':
- if ((d != ' ') && !apr_isdigit(d))
- return 0;
- break;
- default:
- if (mask[i] != d)
- return 0;
- break;
- }
- }
- return 0; /* We only get here if mask is corrupted (exceeds 256) */
-}
-
-
-/*
- * Parses an HTTP date in one of three standard forms:
- *
- * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
- * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
- * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
- *
- * and returns the time_t number of seconds since 1 Jan 1970 GMT, or
- * 0 if this would be out of range or if the date is invalid.
- *
- * The restricted HTTP syntax is
- *
- * HTTP-date = rfc1123-date | rfc850-date | asctime-date
- *
- * rfc1123-date = wkday "," SP date1 SP time SP "GMT"
- * rfc850-date = weekday "," SP date2 SP time SP "GMT"
- * asctime-date = wkday SP date3 SP time SP 4DIGIT
- *
- * date1 = 2DIGIT SP month SP 4DIGIT
- * ; day month year (e.g., 02 Jun 1982)
- * date2 = 2DIGIT "-" month "-" 2DIGIT
- * ; day-month-year (e.g., 02-Jun-82)
- * date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
- * ; month day (e.g., Jun 2)
- *
- * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
- * ; 00:00:00 - 23:59:59
- *
- * wkday = "Mon" | "Tue" | "Wed"
- * | "Thu" | "Fri" | "Sat" | "Sun"
- *
- * weekday = "Monday" | "Tuesday" | "Wednesday"
- * | "Thursday" | "Friday" | "Saturday" | "Sunday"
- *
- * month = "Jan" | "Feb" | "Mar" | "Apr"
- * | "May" | "Jun" | "Jul" | "Aug"
- * | "Sep" | "Oct" | "Nov" | "Dec"
- *
- * However, for the sake of robustness (and Netscapeness), we ignore the
- * weekday and anything after the time field (including the timezone).
- *
- * This routine is intended to be very fast; 10x faster than using sscanf.
- *
- * Originally from Andrew Daviel <andrew@vancouver-webpages.com>, 29 Jul 96
- * but many changes since then.
- *
- */
-AP_DECLARE(apr_time_t) ap_parseHTTPdate(const char *date)
-{
- apr_exploded_time_t ds;
- apr_time_t result;
- int mint, mon;
- const char *monstr, *timstr;
- static const int months[12] =
- {
- ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b',
- ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r',
- ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n',
- ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g',
- ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't',
- ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c'};
-
- if (!date)
- return BAD_DATE;
-
- while (*date && apr_isspace(*date)) /* Find first non-whitespace char */
- ++date;
-
- if (*date == '\0')
- return BAD_DATE;
-
- if ((date = strchr(date, ' ')) == NULL) /* Find space after weekday */
- return BAD_DATE;
-
- ++date; /* Now pointing to first char after space, which should be */
- /* start of the actual date information for all 3 formats. */
-
- if (ap_checkmask(date, "## @$$ #### ##:##:## *")) { /* RFC 1123 format */
- ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
- if (ds.tm_year < 0)
- return BAD_DATE;
-
- ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
-
- ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
-
- monstr = date + 3;
- timstr = date + 12;
- }
- else if (ap_checkmask(date, "##-@$$-## ##:##:## *")) { /* RFC 850 format */
- ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
- if (ds.tm_year < 70)
- ds.tm_year += 100;
-
- ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
-
- monstr = date + 3;
- timstr = date + 10;
- }
- else if (ap_checkmask(date, "@$$ ~# ##:##:## ####*")) { /* asctime format */
- ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100;
- if (ds.tm_year < 0)
- return BAD_DATE;
-
- ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0');
-
- if (date[4] == ' ')
- ds.tm_mday = 0;
- else
- ds.tm_mday = (date[4] - '0') * 10;
-
- ds.tm_mday += (date[5] - '0');
-
- monstr = date;
- timstr = date + 7;
- }
- else
- return BAD_DATE;
-
- if (ds.tm_mday <= 0 || ds.tm_mday > 31)
- return BAD_DATE;
-
- ds.tm_hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0');
- ds.tm_min = ((timstr[3] - '0') * 10) + (timstr[4] - '0');
- ds.tm_sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0');
-
- if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61))
- return BAD_DATE;
-
- mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2];
- for (mon = 0; mon < 12; mon++)
- if (mint == months[mon])
- break;
- if (mon == 12)
- return BAD_DATE;
-
- if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10))
- return BAD_DATE;
-
- /* February gets special check for leapyear */
-
- if ((mon == 1) &&
- ((ds.tm_mday > 29)
- || ((ds.tm_mday == 29)
- && ((ds.tm_year & 3)
- || (((ds.tm_year % 100) == 0)
- && (((ds.tm_year % 400) != 100)))))))
- return BAD_DATE;
-
- ds.tm_mon = mon;
-
- /* ap_mplode_time uses tm_usec and tm_gmtoff fields, but they haven't
- * been set yet.
- * It should be safe to just zero out these values.
- * tm_usec is the number of microseconds into the second. HTTP only
- * cares about second granularity.
- * tm_gmtoff is the number of seconds off of GMT the time is. By
- * definition all times going through this function are in GMT, so this
- * is zero.
- */
- ds.tm_usec = 0;
- ds.tm_gmtoff = 0;
- if (apr_implode_time(&result, &ds) != APR_SUCCESS)
- return BAD_DATE;
-
- return result;
-}
diff --git a/server/util_debug.c b/server/util_debug.c
deleted file mode 100644
index f41f697d2d..0000000000
--- a/server/util_debug.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_config.h"
-
-#ifdef AP_DEBUG
-
-/* get rid of the macros we defined in httpd.h */
-#undef strchr
-#undef strrchr
-#undef strstr
-
-char *ap_strchr(char *s, int c)
-{
- return strchr(s,c);
-}
-const char *ap_strchr_c(const char *s, int c)
-{
- return strchr(s,c);
-}
-char *ap_strrchr(char *s, int c)
-{
- return strrchr(s,c);
-}
-const char *ap_strrchr_c(const char *s, int c)
-{
- return strrchr(s,c);
-}
-char *ap_strstr(char *s, char *c)
-{
- return strstr(s,c);
-}
-const char *ap_strstr_c(const char *s, const char *c)
-{
- return strstr(s,c);
-}
-
-
-AP_DECLARE(void *) ap_get_module_config(const ap_conf_vector_t *cv,
- const module *m)
-{
- return ((void **)cv)[m->module_index];
-}
-
-/**
- * Generic accessors for other modules to set at their own module-specific
- * data
- * @param conf_vector The vector in which the modules configuration is stored.
- * usually r->per_dir_config or s->module_config
- * @param m The module to set the data for.
- * @param val The module-specific data to set
- * @deffunc void ap_set_module_config(ap_conf_vector_t *cv, const module *m, void *val)
- */
-AP_DECLARE(void) ap_set_module_config(ap_conf_vector_t *cv, const module *m,
- void *val)
-{
- ((void **)cv)[m->module_index] = val;
-}
-
-
-#endif /* AP_DEBUG */
diff --git a/server/util_ebcdic.c b/server/util_ebcdic.c
deleted file mode 100644
index 75a1b7dd3d..0000000000
--- a/server/util_ebcdic.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "ap_config.h"
-
-#if APR_CHARSET_EBCDIC
-
-#include "apr_strings.h"
-#include "httpd.h"
-#include "http_log.h"
-#include "http_core.h"
-#include "util_ebcdic.h"
-
-apr_status_t ap_init_ebcdic(apr_pool_t *pool)
-{
- apr_status_t rv;
- char buf[80];
-
- rv = apr_xlate_open(&ap_hdrs_to_ascii, "ISO8859-1", APR_DEFAULT_CHARSET, pool);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "apr_xlate_open() failed");
- return rv;
- }
-
- rv = apr_xlate_open(&ap_hdrs_from_ascii, APR_DEFAULT_CHARSET, "ISO8859-1", pool);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "apr_xlate_open() failed");
- return rv;
- }
-
- rv = apr_xlate_open(&ap_locale_to_ascii, "ISO8859-1", APR_LOCALE_CHARSET, pool);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "apr_xlate_open() failed");
- return rv;
- }
-
- rv = apr_xlate_open(&ap_locale_from_ascii, APR_LOCALE_CHARSET, "ISO8859-1", pool);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "apr_xlate_open() failed");
- return rv;
- }
-
- rv = apr_MD5InitEBCDIC(ap_hdrs_to_ascii);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "apr_MD5InitEBCDIC() failed");
- return rv;
- }
-
- rv = apr_base64init_ebcdic(ap_hdrs_to_ascii, ap_hdrs_from_ascii);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "apr_base64init_ebcdic() failed");
- return rv;
- }
-
- rv = apr_SHA1InitEBCDIC(ap_hdrs_to_ascii);
- if (rv) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "apr_SHA1InitEBCDIC() failed");
- return rv;
- }
-
- return APR_SUCCESS;
-}
-
-void ap_xlate_proto_to_ascii(char *buffer, apr_size_t len)
-{
- apr_size_t inbytes_left, outbytes_left;
-
- inbytes_left = outbytes_left = len;
- apr_xlate_conv_buffer(ap_hdrs_to_ascii, buffer, &inbytes_left,
- buffer, &outbytes_left);
-}
-
-void ap_xlate_proto_from_ascii(char *buffer, apr_size_t len)
-{
- apr_size_t inbytes_left, outbytes_left;
-
- inbytes_left = outbytes_left = len;
- apr_xlate_conv_buffer(ap_hdrs_from_ascii, buffer, &inbytes_left,
- buffer, &outbytes_left);
-}
-
-int ap_rvputs_proto_in_ascii(request_rec *r, ...)
-{
- va_list va;
- const char *s;
- char *ascii_s;
- apr_size_t len;
- apr_size_t written = 0;
-
- va_start(va, r);
- while (1) {
- s = va_arg(va, const char *);
- if (s == NULL)
- break;
- len = strlen(s);
- ascii_s = apr_pstrndup(r->pool, s, len);
- ap_xlate_proto_to_ascii(ascii_s, len);
- if (ap_rputs(ascii_s, r) < 0)
- return -1;
- written += len;
- }
- va_end(va);
-
- return written;
-}
-#endif /* APR_CHARSET_EBCDIC */
diff --git a/server/util_filter.c b/server/util_filter.c
deleted file mode 100644
index 2291919eb9..0000000000
--- a/server/util_filter.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_log.h"
-#include "util_filter.h"
-
-/* ### make this visible for direct manipulation?
- * ### use a hash table
- */
-static ap_filter_rec_t *registered_output_filters = NULL;
-static ap_filter_rec_t *registered_input_filters = NULL;
-
-/* NOTE: Apache's current design doesn't allow a pool to be passed thu,
- so we depend on a global to hold the correct pool
-*/
-#define FILTER_POOL apr_global_hook_pool
-#include "apr_hooks.h" /* for apr_global_hook_pool */
-
-/*
-** This macro returns true/false if a given filter should be inserted BEFORE
-** another filter. This will happen when one of: 1) there isn't another
-** filter; 2) that filter has a higher filter type (class); 3) that filter
-** corresponds to a different request.
-*/
-#define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
- || (before_this)->frec->ftype > (f)->frec->ftype \
- || (before_this)->r != (f)->r)
-
-
-static apr_status_t filter_cleanup(void *ctx)
-{
- registered_output_filters = NULL;
- registered_input_filters = NULL;
- return APR_SUCCESS;
-}
-
-static void register_filter(const char *name,
- ap_filter_func filter_func,
- ap_filter_type ftype,
- ap_filter_rec_t **reg_filter_list)
-{
- ap_filter_rec_t *frec = apr_palloc(FILTER_POOL, sizeof(*frec));
-
- frec->name = name;
- frec->filter_func = filter_func;
- frec->ftype = ftype;
-
- frec->next = *reg_filter_list;
- *reg_filter_list = frec;
-
- apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup, apr_pool_cleanup_null);
-}
-
-AP_DECLARE(void) ap_register_input_filter(const char *name,
- ap_in_filter_func filter_func,
- ap_filter_type ftype)
-{
- ap_filter_func f;
- f.in_func = filter_func;
- register_filter(name, f, ftype, &registered_input_filters);
-}
-
-AP_DECLARE(void) ap_register_output_filter(const char *name,
- ap_out_filter_func filter_func,
- ap_filter_type ftype)
-{
- ap_filter_func f;
- f.out_func = filter_func;
- register_filter(name, f, ftype, &registered_output_filters);
-}
-
-static ap_filter_t *add_any_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c,
- ap_filter_rec_t *frec,
- ap_filter_t **r_filters,
- ap_filter_t **c_filters)
-{
- for (; frec != NULL; frec = frec->next) {
- if (!strcasecmp(name, frec->name)) {
- apr_pool_t *p = r ? r->pool : c->pool;
- ap_filter_t *f = apr_pcalloc(p, sizeof(*f));
- ap_filter_t **outf = r ? r_filters : c_filters;
-
- f->frec = frec;
- f->ctx = ctx;
- f->r = r;
- f->c = c;
-
- if (INSERT_BEFORE(f, *outf)) {
- f->next = *outf;
- *outf = f;
- }
- else {
- ap_filter_t *fscan = *outf;
- while (!INSERT_BEFORE(f, fscan->next))
- fscan = fscan->next;
- f->next = fscan->next;
- fscan->next = f;
- }
-
- return f;
- }
- }
-
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
- "an unknown filter was not added: %s", name);
- return NULL;
-}
-
-AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c)
-{
- return add_any_filter(name, ctx, r, c, registered_input_filters,
- r ? &r->input_filters : NULL, &c->input_filters);
-}
-
-AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c)
-{
- return add_any_filter(name, ctx, r, c, registered_output_filters,
- r ? &r->output_filters : NULL, &c->output_filters);
-}
-
-AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
-{
- ap_filter_t *curr;
-
- curr = f->r ? f->r->output_filters : f->c->output_filters;
-
- if (curr == f) {
- if (f->r) {
- f->r->output_filters = f->r->output_filters->next;
- }
- else {
- f->c->output_filters = f->c->output_filters->next;
- }
- return;
- }
-
- while (curr->next != f) {
- curr = curr->next;
- if (curr == NULL) {
- return;
- }
- }
- curr->next = f->next;
-}
-
-/*
- * Read data from the next filter in the filter stack. Data should be
- * modified in the bucket brigade that is passed in. The core allocates the
- * bucket brigade, modules that wish to replace large chunks of data or to
- * save data off to the side should probably create their own temporary
- * brigade especially for that use.
- */
-AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next, apr_bucket_brigade *bb,
- ap_input_mode_t mode, apr_size_t *readbytes)
-{
- if (next) {
- return next->frec->filter_func.in_func(next, bb, mode, readbytes);
- }
- return AP_NOBODY_READ;
-}
-
-/* Pass the buckets to the next filter in the filter stack. If the
- * current filter is a handler, we should get NULL passed in instead of
- * the current filter. At that point, we can just call the first filter in
- * the stack, or r->output_filters.
- */
-AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next, apr_bucket_brigade *bb)
-{
- if (next) {
- apr_bucket *e;
- if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
- /* This is only safe because HTTP_HEADER filter is always in
- * the filter stack. This ensures that there is ALWAYS a
- * request-based filter that we can attach this to. If the
- * HTTP_FILTER is removed, and another filter is not put in its
- * place, then handlers like mod_cgi, which attach their own
- * EOS bucket to the brigade will be broken, because we will
- * get two EOS buckets on the same request.
- */
- next->r->eos_sent = 1;
- }
- return next->frec->filter_func.out_func(next, bb);
- }
- return AP_NOBODY_WROTE;
-}
-
-AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f, apr_bucket_brigade **saveto,
- apr_bucket_brigade **b)
-{
- apr_bucket *e;
- apr_pool_t *p = f->r ? f->r->pool : f->c->pool;
- apr_status_t rv;
-
- /* If have never stored any data in the filter, then we had better
- * create an empty bucket brigade so that we can concat.
- */
- if (!(*saveto)) {
- *saveto = apr_brigade_create(p);
- }
-
- APR_RING_FOREACH(e, &(*b)->list, apr_bucket, link) {
- rv = apr_bucket_setaside(e);
- if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
- return rv;
- }
- }
- APR_BRIGADE_CONCAT(*saveto, *b);
- return APR_SUCCESS;
-}
-
-AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb, void *ctx)
-{
- ap_filter_t *f = ctx;
-
- return ap_pass_brigade(f, bb);
-}
-
-AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
-{
- apr_bucket *b;
-
- b = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- return ap_pass_brigade(f, bb);
-}
-
-AP_DECLARE_NONSTD(int) ap_fputstrs(ap_filter_t *f, apr_bucket_brigade *bb, ...)
-{
- va_list args;
- int res;
-
- va_start(args, bb);
- res = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
- va_end(args);
- return res;
-}
-
-AP_DECLARE_NONSTD(int) ap_fprintf(ap_filter_t *f, apr_bucket_brigade *bb, const char *fmt, ...){
- va_list args;
- int res;
-
- va_start(args, fmt);
- res = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
- va_end(args);
- return res;
-}
-
diff --git a/server/util_md5.c b/server/util_md5.c
deleted file mode 100644
index 9f19d62add..0000000000
--- a/server/util_md5.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/************************************************************************
- * NCSA HTTPd Server
- * Software Development Group
- * National Center for Supercomputing Applications
- * University of Illinois at Urbana-Champaign
- * 605 E. Springfield, Champaign, IL 61820
- * httpd@ncsa.uiuc.edu
- *
- * Copyright (C) 1995, Board of Trustees of the University of Illinois
- *
- ************************************************************************
- *
- * md5.c: NCSA HTTPd code which uses the md5c.c RSA Code
- *
- * Original Code Copyright (C) 1994, Jeff Hostetler, Spyglass, Inc.
- * Portions of Content-MD5 code Copyright (C) 1993, 1994 by Carnegie Mellon
- * University (see Copyright below).
- * Portions of Content-MD5 code Copyright (C) 1991 Bell Communications
- * Research, Inc. (Bellcore) (see Copyright below).
- * Portions extracted from mpack, John G. Myers - jgm+@cmu.edu
- * Content-MD5 Code contributed by Martin Hamilton (martin@net.lut.ac.uk)
- *
- */
-
-
-
-/* md5.c --Module Interface to MD5. */
-/* Jeff Hostetler, Spyglass, Inc., 1994. */
-
-#include "ap_config.h"
-#include "apr_portable.h"
-#include "apr_strings.h"
-#include "httpd.h"
-#include "util_md5.h"
-#include "util_ebcdic.h"
-
-AP_DECLARE(char *) ap_md5_binary(apr_pool_t *p, const unsigned char *buf, int length)
-{
- const char *hex = "0123456789abcdef";
- apr_md5_ctx_t my_md5;
- unsigned char hash[MD5_DIGESTSIZE];
- char *r, result[33];
- int i;
-
- /*
- * Take the MD5 hash of the string argument.
- */
-
- apr_md5_init(&my_md5);
-#if APR_CHARSET_EBCDIC
- apr_md5_set_xlate(&my_md5, ap_hdrs_to_ascii);
-#endif
- apr_md5_update(&my_md5, buf, (unsigned int)length);
- apr_md5_final(hash, &my_md5);
-
- for (i = 0, r = result; i < MD5_DIGESTSIZE; i++) {
- *r++ = hex[hash[i] >> 4];
- *r++ = hex[hash[i] & 0xF];
- }
- *r = '\0';
-
- return apr_pstrdup(p, result);
-}
-
-AP_DECLARE(char *) ap_md5(apr_pool_t *p, const unsigned char *string)
-{
- return ap_md5_binary(p, string, (int) strlen((char *)string));
-}
-
-/* these portions extracted from mpack, John G. Myers - jgm+@cmu.edu */
-
-/* (C) Copyright 1993,1994 by Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without
- * fee, provided that the above copyright notice appear in all copies
- * and that both that copyright notice and this permission notice
- * appear in supporting documentation, and that the name of Carnegie
- * Mellon University not be used in advertising or publicity
- * pertaining to distribution of the software without specific,
- * written prior permission. Carnegie Mellon University makes no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied
- * warranty.
- *
- * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
- * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
- *
- * Permission to use, copy, modify, and distribute this material
- * for any purpose and without fee is hereby granted, provided
- * that the above copyright notice and this permission notice
- * appear in all copies, and that the name of Bellcore not be
- * used in advertising or publicity pertaining to this
- * material without the specific, prior written permission
- * of an authorized representative of Bellcore. BELLCORE
- * MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
- * OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
- * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
- */
-
-static char basis_64[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-AP_DECLARE(char *) ap_md5contextTo64(apr_pool_t *a, apr_md5_ctx_t *context)
-{
- unsigned char digest[18];
- char *encodedDigest;
- int i;
- char *p;
-
- encodedDigest = (char *) apr_pcalloc(a, 25 * sizeof(char));
-
- apr_md5_final(digest, context);
- digest[sizeof(digest) - 1] = digest[sizeof(digest) - 2] = 0;
-
- p = encodedDigest;
- for (i = 0; i < sizeof(digest); i += 3) {
- *p++ = basis_64[digest[i] >> 2];
- *p++ = basis_64[((digest[i] & 0x3) << 4) | ((int) (digest[i + 1] & 0xF0) >> 4)];
- *p++ = basis_64[((digest[i + 1] & 0xF) << 2) | ((int) (digest[i + 2] & 0xC0) >> 6)];
- *p++ = basis_64[digest[i + 2] & 0x3F];
- }
- *p-- = '\0';
- *p-- = '=';
- *p-- = '=';
- return encodedDigest;
-}
-
-AP_DECLARE(char *) ap_md5digest(apr_pool_t *p, apr_file_t *infile)
-{
- apr_md5_ctx_t context;
- unsigned char buf[1000];
- long length = 0;
- apr_size_t nbytes;
- apr_off_t offset = 0L;
-
- apr_md5_init(&context);
- nbytes = sizeof(buf);
- while (apr_file_read(infile, buf, &nbytes) == APR_SUCCESS) {
- length += nbytes;
- apr_md5_update(&context, buf, nbytes);
- }
- apr_file_seek(infile, APR_SET, &offset);
- return ap_md5contextTo64(p, &context);
-}
-
diff --git a/server/util_script.c b/server/util_script.c
deleted file mode 100644
index 875bec9c7a..0000000000
--- a/server/util_script.c
+++ /dev/null
@@ -1,652 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_lib.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_request.h" /* for sub_req_lookup_uri() */
-#include "util_script.h"
-#include "util_date.h" /* For parseHTTPdate() */
-#include "util_ebcdic.h"
-
-#ifdef OS2
-#define INCL_DOS
-#include <os2.h>
-#endif
-
-/*
- * Various utility functions which are common to a whole lot of
- * script-type extensions mechanisms, and might as well be gathered
- * in one place (if only to avoid creating inter-module dependancies
- * where there don't have to be).
- */
-
-#define MALFORMED_MESSAGE "malformed header from script. Bad header="
-#define MALFORMED_HEADER_LENGTH_TO_SHOW 30
-
-static char *http2env(apr_pool_t *a, char *w)
-{
- char *res = apr_pstrcat(a, "HTTP_", w, NULL);
- char *cp = res;
-
- while (*++cp) {
- if (!apr_isalnum(*cp) && *cp != '_') {
- *cp = '_';
- }
- else {
- *cp = apr_toupper(*cp);
- }
- }
-
- return res;
-}
-
-AP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t)
-{
- apr_array_header_t *env_arr = apr_table_elts(t);
- apr_table_entry_t *elts = (apr_table_entry_t *) env_arr->elts;
- char **env = (char **) apr_palloc(p, (env_arr->nelts + 2) * sizeof(char *));
- int i, j;
- char *tz;
- char *whack;
-
- j = 0;
- if (!apr_table_get(t, "TZ")) {
- tz = getenv("TZ");
- if (tz != NULL) {
- env[j++] = apr_pstrcat(p, "TZ=", tz, NULL);
- }
- }
- for (i = 0; i < env_arr->nelts; ++i) {
- if (!elts[i].key) {
- continue;
- }
- env[j] = apr_pstrcat(p, elts[i].key, "=", elts[i].val, NULL);
- whack = env[j];
- if (apr_isdigit(*whack)) {
- *whack++ = '_';
- }
- while (*whack != '=') {
- if (!apr_isalnum(*whack) && *whack != '_') {
- *whack = '_';
- }
- ++whack;
- }
- ++j;
- }
-
- env[j] = NULL;
- return env;
-}
-
-AP_DECLARE(void) ap_add_common_vars(request_rec *r)
-{
- apr_table_t *e;
- server_rec *s = r->server;
- conn_rec *c = r->connection;
- const char *rem_logname;
- char *env_path;
-#if defined(WIN32) || defined(OS2)
- char *env_temp;
-#endif
- const char *host;
- apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
- apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
- int i;
- apr_port_t rport;
- apr_sockaddr_t *remotesa;
-
- /* use a temporary apr_table_t which we'll overlap onto
- * r->subprocess_env later
- */
- e = apr_table_make(r->pool, 25 + hdrs_arr->nelts);
-
- /* First, add environment vars from headers... this is as per
- * CGI specs, though other sorts of scripting interfaces see
- * the same vars...
- */
-
- for (i = 0; i < hdrs_arr->nelts; ++i) {
- if (!hdrs[i].key) {
- continue;
- }
-
- /* A few headers are special cased --- Authorization to prevent
- * rogue scripts from capturing passwords; content-type and -length
- * for no particular reason.
- */
-
- if (!strcasecmp(hdrs[i].key, "Content-type")) {
- apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val);
- }
- else if (!strcasecmp(hdrs[i].key, "Content-length")) {
- apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val);
- }
- /*
- * You really don't want to disable this check, since it leaves you
- * wide open to CGIs stealing passwords and people viewing them
- * in the environment with "ps -e". But, if you must...
- */
-#ifndef SECURITY_HOLE_PASS_AUTHORIZATION
- else if (!strcasecmp(hdrs[i].key, "Authorization")
- || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
- continue;
- }
-#endif
- else {
- apr_table_addn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val);
- }
- }
-
- if (!(env_path = getenv("PATH"))) {
- env_path = DEFAULT_PATH;
- }
- apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_path));
-
-#ifdef WIN32
- if (env_temp = getenv("SystemRoot")) {
- apr_table_addn(e, "SystemRoot", env_temp);
- }
- if (env_temp = getenv("COMSPEC")) {
- apr_table_addn(e, "COMSPEC", env_temp);
- }
- if (env_temp = getenv("WINDIR")) {
- apr_table_addn(e, "WINDIR", env_temp);
- }
-#endif
-
-#ifdef OS2
- if ((env_temp = getenv("COMSPEC")) != NULL) {
- apr_table_addn(e, "COMSPEC", env_temp);
- }
- if ((env_temp = getenv("ETC")) != NULL) {
- apr_table_addn(e, "ETC", env_temp);
- }
- if ((env_temp = getenv("DPATH")) != NULL) {
- apr_table_addn(e, "DPATH", env_temp);
- }
- if ((env_temp = getenv("PERLLIB_PREFIX")) != NULL) {
- apr_table_addn(e, "PERLLIB_PREFIX", env_temp);
- }
-#endif
-
- apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
- apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version());
- apr_table_addn(e, "SERVER_NAME", ap_get_server_name(r));
- apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */
- apr_table_addn(e, "SERVER_PORT",
- apr_psprintf(r->pool, "%u", ap_get_server_port(r)));
- host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL);
- if (host) {
- apr_table_addn(e, "REMOTE_HOST", host);
- }
- apr_table_addn(e, "REMOTE_ADDR", c->remote_ip);
- apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */
- apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
- apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
-
- apr_socket_addr_get(&remotesa, APR_REMOTE, c->client_socket);
- apr_sockaddr_port_get(&rport, remotesa);
- apr_table_addn(e, "REMOTE_PORT", apr_psprintf(r->pool, "%d", rport));
-
- if (r->user) {
- apr_table_addn(e, "REMOTE_USER", r->user);
- }
- if (r->ap_auth_type) {
- apr_table_addn(e, "AUTH_TYPE", r->ap_auth_type);
- }
- rem_logname = ap_get_remote_logname(r);
- if (rem_logname) {
- apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, rem_logname));
- }
-
- /* Apache custom error responses. If we have redirected set two new vars */
-
- if (r->prev) {
- if (r->prev->args) {
- apr_table_addn(e, "REDIRECT_QUERY_STRING", r->prev->args);
- }
- if (r->prev->uri) {
- apr_table_addn(e, "REDIRECT_URL", r->prev->uri);
- }
- }
-
- apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET);
-}
-
-/* This "cute" little function comes about because the path info on
- * filenames and URLs aren't always the same. So we take the two,
- * and find as much of the two that match as possible.
- */
-
-AP_DECLARE(int) ap_find_path_info(const char *uri, const char *path_info)
-{
- int lu = strlen(uri);
- int lp = strlen(path_info);
-
- while (lu-- && lp-- && uri[lu] == path_info[lp]);
-
- if (lu == -1) {
- lu = 0;
- }
-
- while (uri[lu] != '\0' && uri[lu] != '/') {
- lu++;
- }
- return lu;
-}
-
-AP_DECLARE(void) ap_add_cgi_vars(request_rec *r)
-{
- apr_table_t *e = r->subprocess_env;
-
- apr_table_setn(e, "GATEWAY_INTERFACE", "CGI/1.1");
- apr_table_setn(e, "SERVER_PROTOCOL", r->protocol);
- apr_table_setn(e, "REQUEST_METHOD", r->method);
- apr_table_setn(e, "QUERY_STRING", r->args ? r->args : "");
- apr_table_setn(e, "REQUEST_URI", r->unparsed_uri);
-
- /* Note that the code below special-cases scripts run from includes,
- * because it "knows" that the sub_request has been hacked to have the
- * args and path_info of the original request, and not any that may have
- * come with the script URI in the include command. Ugh.
- */
-
- if (!strcmp(r->protocol, "INCLUDED")) {
- apr_table_setn(e, "SCRIPT_NAME", r->uri);
- if (r->path_info && *r->path_info) {
- apr_table_setn(e, "PATH_INFO", r->path_info);
- }
- }
- else if (!r->path_info || !*r->path_info) {
- apr_table_setn(e, "SCRIPT_NAME", r->uri);
- }
- else {
- int path_info_start = ap_find_path_info(r->uri, r->path_info);
-
- apr_table_setn(e, "SCRIPT_NAME",
- apr_pstrndup(r->pool, r->uri, path_info_start));
-
- apr_table_setn(e, "PATH_INFO", r->path_info);
- }
-
- if (r->path_info && r->path_info[0]) {
- /*
- * To get PATH_TRANSLATED, treat PATH_INFO as a URI path.
- * Need to re-escape it for this, since the entire URI was
- * un-escaped before we determined where the PATH_INFO began.
- */
- request_rec *pa_req;
-
- pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r,
- NULL);
-
- if (pa_req->filename) {
-#ifdef WIN32
- char buffer[HUGE_STRING_LEN];
-#endif
- char *pt = apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info,
- NULL);
-#ifdef WIN32
- /* We need to make this a real Windows path name */
- GetFullPathName(pt, HUGE_STRING_LEN, buffer, NULL);
- apr_table_setn(e, "PATH_TRANSLATED", apr_pstrdup(r->pool, buffer));
-#else
- apr_table_setn(e, "PATH_TRANSLATED", pt);
-#endif
- }
- ap_destroy_sub_req(pa_req);
- }
-}
-
-
-static int set_cookie_doo_doo(void *v, const char *key, const char *val)
-{
- apr_table_addn(v, key, val);
- return 1;
-}
-
-AP_DECLARE(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
- int (*getsfunc) (char *, int, void *),
- void *getsfunc_data)
-{
- char x[MAX_STRING_LEN];
- char *w, *l;
- int p;
- int cgi_status = HTTP_OK;
- apr_table_t *merge;
- apr_table_t *cookie_table;
-
- if (buffer) {
- *buffer = '\0';
- }
- w = buffer ? buffer : x;
-
- /* temporary place to hold headers to merge in later */
- merge = apr_table_make(r->pool, 10);
-
- /* The HTTP specification says that it is legal to merge duplicate
- * headers into one. Some browsers that support Cookies don't like
- * merged headers and prefer that each Set-Cookie header is sent
- * separately. Lets humour those browsers by not merging.
- * Oh what a pain it is.
- */
- cookie_table = apr_table_make(r->pool, 2);
- apr_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL);
-
- while (1) {
-
- if ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data) == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Premature end of script headers: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* Delete terminal (CR?)LF */
-
- p = strlen(w);
- /* Indeed, the host's '\n':
- '\012' for UNIX; '\015' for MacOS; '\025' for OS/390
- -- whatever the script generates.
- */
- if (p > 0 && w[p - 1] == '\n') {
- if (p > 1 && w[p - 2] == CR) {
- w[p - 2] = '\0';
- }
- else {
- w[p - 1] = '\0';
- }
- }
-
- /*
- * If we've finished reading the headers, check to make sure any
- * HTTP/1.1 conditions are met. If so, we're done; normal processing
- * will handle the script's output. If not, just return the error.
- * The appropriate thing to do would be to send the script process a
- * SIGPIPE to let it know we're ignoring it, close the channel to the
- * script process, and *then* return the failed-to-meet-condition
- * error. Otherwise we'd be waiting for the script to finish
- * blithering before telling the client the output was no good.
- * However, we don't have the information to do that, so we have to
- * leave it to an upper layer.
- */
- if (w[0] == '\0') {
- int cond_status = OK;
-
- if ((cgi_status == HTTP_OK) && (r->method_number == M_GET)) {
- cond_status = ap_meets_conditions(r);
- }
- apr_table_overlap(r->err_headers_out, merge,
- APR_OVERLAP_TABLES_MERGE);
- if (!apr_is_empty_table(cookie_table)) {
- /* the cookies have already been copied to the cookie_table */
- apr_table_unset(r->err_headers_out, "Set-Cookie");
- r->err_headers_out = apr_table_overlay(r->pool,
- r->err_headers_out, cookie_table);
- }
- return cond_status;
- }
-
- /* if we see a bogus header don't ignore it. Shout and scream */
-
-#if APR_CHARSET_EBCDIC
- /* Chances are that we received an ASCII header text instead of
- * the expected EBCDIC header lines. Try to auto-detect:
- */
- if (!(l = strchr(w, ':'))) {
- int maybeASCII = 0, maybeEBCDIC = 0;
- unsigned char *cp, native;
- apr_size_t inbytes_left, outbytes_left;
-
- for (cp = w; *cp != '\0'; ++cp) {
- native = apr_xlate_conv_byte(ap_hdrs_from_ascii, *cp);
- if (isprint(*cp) && !isprint(native))
- ++maybeEBCDIC;
- if (!isprint(*cp) && isprint(native))
- ++maybeASCII;
- }
- if (maybeASCII > maybeEBCDIC) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server,
- "CGI Interface Error: Script headers apparently ASCII: (CGI = %s)",
- r->filename);
- inbytes_left = outbytes_left = cp - w;
- apr_xlate_conv_buffer(ap_hdrs_from_ascii,
- w, &inbytes_left, w, &outbytes_left);
- }
- }
-#endif /*APR_CHARSET_EBCDIC*/
- if (!(l = strchr(w, ':'))) {
- char malformed[(sizeof MALFORMED_MESSAGE) + 1
- + MALFORMED_HEADER_LENGTH_TO_SHOW];
-
- strcpy(malformed, MALFORMED_MESSAGE);
- strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW);
-
- if (!buffer) {
- /* Soak up all the script output - may save an outright kill */
- while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) {
- continue;
- }
- }
-
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "%s: %s", malformed, r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- *l++ = '\0';
- while (*l && apr_isspace(*l)) {
- ++l;
- }
-
- if (!strcasecmp(w, "Content-type")) {
- char *tmp;
-
- /* Nuke trailing whitespace */
-
- char *endp = l + strlen(l) - 1;
- while (endp > l && apr_isspace(*endp)) {
- *endp-- = '\0';
- }
-
- tmp = apr_pstrdup(r->pool, l);
- ap_content_type_tolower(tmp);
- r->content_type = tmp;
- }
- /*
- * If the script returned a specific status, that's what
- * we'll use - otherwise we assume 200 OK.
- */
- else if (!strcasecmp(w, "Status")) {
- r->status = cgi_status = atoi(l);
- r->status_line = apr_pstrdup(r->pool, l);
- }
- else if (!strcasecmp(w, "Location")) {
- apr_table_set(r->headers_out, w, l);
- }
- else if (!strcasecmp(w, "Content-Length")) {
- apr_table_set(r->headers_out, w, l);
- }
- else if (!strcasecmp(w, "Transfer-Encoding")) {
- apr_table_set(r->headers_out, w, l);
- }
- /*
- * If the script gave us a Last-Modified header, we can't just
- * pass it on blindly because of restrictions on future values.
- */
- else if (!strcasecmp(w, "Last-Modified")) {
- ap_update_mtime(r, ap_parseHTTPdate(l));
- ap_set_last_modified(r);
- }
- else if (!strcasecmp(w, "Set-Cookie")) {
- apr_table_add(cookie_table, w, l);
- }
- else {
- apr_table_add(merge, w, l);
- }
- }
-}
-
-static int getsfunc_FILE(char *buf, int len, void *f)
-{
- return apr_file_gets(buf, len, (apr_file_t *) f) == APR_SUCCESS;
-}
-
-AP_DECLARE(int) ap_scan_script_header_err(request_rec *r, apr_file_t *f,
- char *buffer)
-{
- return ap_scan_script_header_err_core(r, buffer, getsfunc_FILE, f);
-}
-
-struct vastrs {
- va_list args;
- int arg;
- const char *curpos;
-};
-
-static int getsfunc_STRING(char *w, int len, void *pvastrs)
-{
- struct vastrs *strs = (struct vastrs*) pvastrs;
- const char *p;
- int t;
-
- if (!strs->curpos || !*strs->curpos)
- return 0;
- p = ap_strchr_c(strs->curpos, '\n');
- if (p)
- ++p;
- else
- p = ap_strchr_c(strs->curpos, '\0');
- t = p - strs->curpos;
- if (t > len)
- t = len;
- strncpy (w, strs->curpos, t);
- w[t] = '\0';
- if (!strs->curpos[t]) {
- ++strs->arg;
- strs->curpos = va_arg(strs->args, const char *);
- }
- else
- strs->curpos += t;
- return t;
-}
-
-/* ap_scan_script_header_err_strs() accepts additional const char* args...
- * each is treated as one or more header lines, and the first non-header
- * character is returned to **arg, **data. (The first optional arg is
- * counted as 0.)
- */
-AP_DECLARE_NONSTD(int) ap_scan_script_header_err_strs(request_rec *r,
- char *buffer,
- const char **termch,
- int *termarg, ...)
-{
- struct vastrs strs;
- int res;
-
- va_start(strs.args, termarg);
- strs.arg = 0;
- strs.curpos = va_arg(strs.args, char*);
- res = ap_scan_script_header_err_core(r, buffer, getsfunc_STRING, (void *) &strs);
- if (termch)
- *termch = strs.curpos;
- if (termarg)
- *termarg = strs.arg;
- va_end(strs.args);
- return res;
-}
-
-AP_DECLARE(void) ap_send_size(apr_ssize_t size, request_rec *r)
-{
- /* XXX: this -1 thing is a gross hack */
- if (size == (apr_ssize_t)-1) {
- ap_rputs(" -", r);
- }
- else if (!size) {
- ap_rputs(" 0k", r);
- }
- else if (size < 1024) {
- ap_rputs(" 1k", r);
- }
- else if (size < 1048576) {
- ap_rprintf(r, "%4" APR_SSIZE_T_FMT "k", (size + 512) / 1024);
- }
- else if (size < 103809024) {
- ap_rprintf(r, "%4.1fM", size / 1048576.0);
- }
- else {
- ap_rprintf(r, "%4" APR_SSIZE_T_FMT "M", (size + 524288) / 1048576);
- }
-}
-
diff --git a/server/util_uri.c b/server/util_uri.c
deleted file mode 100644
index 508c6f199c..0000000000
--- a/server/util_uri.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * util_uri.c: URI related utility things
- *
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_log.h"
-#include "util_uri.h"
-
-/* Some WWW schemes and their default ports; this is basically /etc/services */
-/* This will become global when the protocol abstraction comes */
-/* As the schemes are searched by a linear search, */
-/* they are sorted by their expected frequency */
-static schemes_t schemes[] =
-{
- {"http", DEFAULT_HTTP_PORT},
- {"ftp", DEFAULT_FTP_PORT},
- {"https", DEFAULT_HTTPS_PORT},
- {"gopher", DEFAULT_GOPHER_PORT},
- {"wais", DEFAULT_WAIS_PORT},
- {"nntp", DEFAULT_NNTP_PORT},
- {"snews", DEFAULT_SNEWS_PORT},
- {"prospero", DEFAULT_PROSPERO_PORT},
- { NULL, 0xFFFF } /* unknown port */
-};
-
-
-AP_DECLARE(apr_port_t) ap_default_port_for_scheme(const char *scheme_str)
-{
- schemes_t *scheme;
-
- for (scheme = schemes; scheme->name != NULL; ++scheme)
- if (strcasecmp(scheme_str, scheme->name) == 0)
- return scheme->default_port;
-
- return 0;
-}
-
-AP_DECLARE(apr_port_t) ap_default_port_for_request(const request_rec *r)
-{
- return (r->parsed_uri.scheme)
- ? ap_default_port_for_scheme(r->parsed_uri.scheme)
- : 0;
-}
-
-/* Unparse a uri_components structure to an URI string.
- * Optionally suppress the password for security reasons.
- */
-AP_DECLARE(char *) ap_unparse_uri_components(apr_pool_t *p, const uri_components *uptr, unsigned flags)
-{
- char *ret = "";
-
- /* If suppressing the site part, omit both user name & scheme://hostname */
- if (!(flags & UNP_OMITSITEPART)) {
-
- /* Construct a "user:password@" string, honoring the passed UNP_ flags: */
- if (uptr->user||uptr->password)
- ret = apr_pstrcat (p,
- (uptr->user && !(flags & UNP_OMITUSER)) ? uptr->user : "",
- (uptr->password && !(flags & UNP_OMITPASSWORD)) ? ":" : "",
- (uptr->password && !(flags & UNP_OMITPASSWORD))
- ? ((flags & UNP_REVEALPASSWORD) ? uptr->password : "XXXXXXXX")
- : "",
- "@", NULL);
-
- /* Construct scheme://site string */
- if (uptr->hostname) {
- int is_default_port;
-
- is_default_port =
- (uptr->port_str == NULL ||
- uptr->port == 0 ||
- uptr->port == ap_default_port_for_scheme(uptr->scheme));
-
- ret = apr_pstrcat (p,
- uptr->scheme, "://", ret,
- uptr->hostname ? uptr->hostname : "",
- is_default_port ? "" : ":",
- is_default_port ? "" : uptr->port_str,
- NULL);
- }
- }
-
- /* Should we suppress all path info? */
- if (!(flags & UNP_OMITPATHINFO)) {
- /* Append path, query and fragment strings: */
- ret = apr_pstrcat (p,
- ret,
- uptr->path ? uptr->path : "",
- (uptr->query && !(flags & UNP_OMITQUERY)) ? "?" : "",
- (uptr->query && !(flags & UNP_OMITQUERY)) ? uptr->query : "",
- (uptr->fragment && !(flags & UNP_OMITQUERY)) ? "#" : NULL,
- (uptr->fragment && !(flags & UNP_OMITQUERY)) ? uptr->fragment : NULL,
- NULL);
- }
- return ret;
-}
-
-/* Here is the hand-optimized parse_uri_components(). There are some wild
- * tricks we could pull in assembly language that we don't pull here... like we
- * can do word-at-time scans for delimiter characters using the same technique
- * that fast memchr()s use. But that would be way non-portable. -djg
- */
-
-/* We have a apr_table_t that we can index by character and it tells us if the
- * character is one of the interesting delimiters. Note that we even get
- * compares for NUL for free -- it's just another delimiter.
- */
-
-#define T_COLON 0x01 /* ':' */
-#define T_SLASH 0x02 /* '/' */
-#define T_QUESTION 0x04 /* '?' */
-#define T_HASH 0x08 /* '#' */
-#define T_NUL 0x80 /* '\0' */
-
-/* the uri_delims.h file is autogenerated by gen_uri_delims.c */
-#include "uri_delims.h"
-
-/* it works like this:
- if (uri_delims[ch] & NOTEND_foobar) {
- then we're not at a delimiter for foobar
- }
-*/
-
-/* Note that we optimize the scheme scanning here, we cheat and let the
- * compiler know that it doesn't have to do the & masking.
- */
-#define NOTEND_SCHEME (0xff)
-#define NOTEND_HOSTINFO (T_SLASH | T_QUESTION | T_HASH | T_NUL)
-#define NOTEND_PATH (T_QUESTION | T_HASH | T_NUL)
-
-/* parse_uri_components():
- * Parse a given URI, fill in all supplied fields of a uri_components
- * structure. This eliminates the necessity of extracting host, port,
- * path, query info repeatedly in the modules.
- * Side effects:
- * - fills in fields of uri_components *uptr
- * - none on any of the r->* fields
- */
-AP_DECLARE(int) ap_parse_uri_components(apr_pool_t *p, const char *uri, uri_components *uptr)
-{
- const char *s;
- const char *s1;
- const char *hostinfo;
- char *endstr;
- int port;
-
- /* Initialize the structure. parse_uri() and parse_uri_components()
- * can be called more than once per request.
- */
- memset (uptr, '\0', sizeof(*uptr));
- uptr->is_initialized = 1;
-
- /* We assume the processor has a branch predictor like most --
- * it assumes forward branches are untaken and backwards are taken. That's
- * the reason for the gotos. -djg
- */
- if (uri[0] == '/') {
-deal_with_path:
- /* we expect uri to point to first character of path ... remember
- * that the path could be empty -- http://foobar?query for example
- */
- s = uri;
- while ((uri_delims[*(unsigned char *)s] & NOTEND_PATH) == 0) {
- ++s;
- }
- if (s != uri) {
- uptr->path = apr_pstrndup(p, uri, s - uri);
- }
- if (*s == 0) {
- return HTTP_OK;
- }
- if (*s == '?') {
- ++s;
- s1 = ap_strchr_c(s, '#');
- if (s1) {
- uptr->fragment = apr_pstrdup(p, s1 + 1);
- uptr->query = apr_pstrndup(p, s, s1 - s);
- }
- else {
- uptr->query = apr_pstrdup(p, s);
- }
- return HTTP_OK;
- }
- /* otherwise it's a fragment */
- uptr->fragment = apr_pstrdup(p, s + 1);
- return HTTP_OK;
- }
-
- /* find the scheme: */
- s = uri;
- while ((uri_delims[*(unsigned char *)s] & NOTEND_SCHEME) == 0) {
- ++s;
- }
- /* scheme must be non-empty and followed by :// */
- if (s == uri || s[0] != ':' || s[1] != '/' || s[2] != '/') {
- goto deal_with_path; /* backwards predicted taken! */
- }
-
- uptr->scheme = apr_pstrndup(p, uri, s - uri);
- s += 3;
- hostinfo = s;
- while ((uri_delims[*(unsigned char *)s] & NOTEND_HOSTINFO) == 0) {
- ++s;
- }
- uri = s; /* whatever follows hostinfo is start of uri */
- uptr->hostinfo = apr_pstrndup(p, hostinfo, uri - hostinfo);
-
- /* If there's a username:password@host:port, the @ we want is the last @...
- * too bad there's no memrchr()... For the C purists, note that hostinfo
- * is definately not the first character of the original uri so therefore
- * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C.
- */
- do {
- --s;
- } while (s >= hostinfo && *s != '@');
- if (s < hostinfo) {
- /* again we want the common case to be fall through */
-deal_with_host:
- /* We expect hostinfo to point to the first character of
- * the hostname. If there's a port it is the first colon.
- */
- s = memchr(hostinfo, ':', uri - hostinfo);
- if (s == NULL) {
- /* we expect the common case to have no port */
- uptr->hostname = apr_pstrndup(p, hostinfo, uri - hostinfo);
- goto deal_with_path;
- }
- uptr->hostname = apr_pstrndup(p, hostinfo, s - hostinfo);
- ++s;
- uptr->port_str = apr_pstrndup(p, s, uri - s);
- if (uri != s) {
- port = strtol(uptr->port_str, &endstr, 10);
- uptr->port = port;
- if (*endstr == '\0') {
- goto deal_with_path;
- }
- /* Invalid characters after ':' found */
- return HTTP_BAD_REQUEST;
- }
- uptr->port = ap_default_port_for_scheme(uptr->scheme);
- goto deal_with_path;
- }
-
- /* first colon delimits username:password */
- s1 = memchr(hostinfo, ':', s - hostinfo);
- if (s1) {
- uptr->user = apr_pstrndup(p, hostinfo, s1 - hostinfo);
- ++s1;
- uptr->password = apr_pstrndup(p, s1, s - s1);
- }
- else {
- uptr->user = apr_pstrndup(p, hostinfo, s - hostinfo);
- }
- hostinfo = s + 1;
- goto deal_with_host;
-}
-
-/* Special case for CONNECT parsing: it comes with the hostinfo part only */
-/* See the INTERNET-DRAFT document "Tunneling SSL Through a WWW Proxy"
- * currently at http://www.mcom.com/newsref/std/tunneling_ssl.html
- * for the format of the "CONNECT host:port HTTP/1.0" request
- */
-AP_DECLARE(int) ap_parse_hostinfo_components(apr_pool_t *p, const char *hostinfo, uri_components *uptr)
-{
- const char *s;
- char *endstr;
-
- /* Initialize the structure. parse_uri() and parse_uri_components()
- * can be called more than once per request.
- */
- memset (uptr, '\0', sizeof(*uptr));
- uptr->is_initialized = 1;
- uptr->hostinfo = apr_pstrdup(p, hostinfo);
-
- /* We expect hostinfo to point to the first character of
- * the hostname. There must be a port, separated by a colon
- */
- s = ap_strchr_c(hostinfo, ':');
- if (s == NULL) {
- return HTTP_BAD_REQUEST;
- }
- uptr->hostname = apr_pstrndup(p, hostinfo, s - hostinfo);
- ++s;
- uptr->port_str = apr_pstrdup(p, s);
- if (*s != '\0') {
- uptr->port = (unsigned short) strtol(uptr->port_str, &endstr, 10);
- if (*endstr == '\0') {
- return HTTP_OK;
- }
- /* Invalid characters after ':' found */
- }
- return HTTP_BAD_REQUEST;
-}
diff --git a/server/util_xml.c b/server/util_xml.c
deleted file mode 100644
index 9c617b298c..0000000000
--- a/server/util_xml.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_xml.h"
-
-#include "httpd.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_core.h"
-
-#include "util_xml.h"
-
-
-#define READ_BLOCKSIZE 2048 /* used for reading input blocks */
-
-
-AP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc)
-{
- apr_xml_parser *parser;
- int result;
- apr_status_t status;
- char errbuf[200];
-
- if ((result = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK)
- return result;
-
- if (r->remaining == 0) {
- *pdoc = NULL;
- return OK;
- }
-
- parser = apr_xml_parser_create(r->pool);
-
- if (ap_should_client_block(r)) {
- long len;
- char *buffer;
- apr_size_t total_read = 0;
- apr_size_t limit_xml_body = ap_get_limit_xml_body(r);
-
- /* allocate our working buffer */
- buffer = apr_palloc(r->pool, READ_BLOCKSIZE);
-
- /* read the body, stuffing it into the parser */
- while ((len = ap_get_client_block(r, buffer, READ_BLOCKSIZE)) > 0) {
- total_read += len;
- if (limit_xml_body && total_read > limit_xml_body) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "XML request body is larger than the configured "
- "limit of %lu", (unsigned long)limit_xml_body);
- goto read_error;
- }
-
- status = apr_xml_parser_feed(parser, buffer, len);
- if (status)
- goto parser_error;
- }
- if (len == -1) {
- /* ap_get_client_block() has logged an error */
- goto read_error;
- }
- }
-
- /* tell the parser that we're done */
- status = apr_xml_parser_done(parser, pdoc);
- if (status)
- goto parser_error;
-
- return OK;
-
- parser_error:
- (void) apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf));
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "%s", errbuf);
-
- /* FALLTHRU */
-
- read_error:
- /* make sure the parser is terminated */
- (void) apr_xml_parser_done(parser, NULL);
-
- /* Apache will supply a default error, plus the error log above. */
- return HTTP_BAD_REQUEST;
-}
diff --git a/server/vhost.c b/server/vhost.c
deleted file mode 100644
index ca373e5916..0000000000
--- a/server/vhost.c
+++ /dev/null
@@ -1,1017 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_vhost.c: functions pertaining to virtual host addresses
- * (configuration and run-time)
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_vhost.h"
-#include "http_protocol.h"
-#include "http_core.h"
-
-#if APR_HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-/*
- * After all the definitions there's an explanation of how it's all put
- * together.
- */
-
-/* meta-list of name-vhosts. Each server_rec can be in possibly multiple
- * lists of name-vhosts.
- */
-typedef struct name_chain name_chain;
-struct name_chain {
- name_chain *next;
- server_addr_rec *sar; /* the record causing it to be in
- * this chain (needed for port comparisons) */
- server_rec *server; /* the server to use on a match */
-};
-
-/* meta-list of ip addresses. Each server_rec can be in possibly multiple
- * hash chains since it can have multiple ips.
- */
-typedef struct ipaddr_chain ipaddr_chain;
-struct ipaddr_chain {
- ipaddr_chain *next;
- server_addr_rec *sar; /* the record causing it to be in
- * this chain (need for both ip addr and port
- * comparisons) */
- server_rec *server; /* the server to use if this matches */
- name_chain *names; /* if non-NULL then a list of name-vhosts
- * sharing this address */
-};
-
-/* This defines the size of the hash apr_table_t used for hashing ip addresses
- * of virtual hosts. It must be a power of two.
- */
-#ifndef IPHASH_TABLE_SIZE
-#define IPHASH_TABLE_SIZE 256
-#endif
-
-/* A (n) bucket hash table, each entry has a pointer to a server rec and
- * a pointer to the other entries in that bucket. Each individual address,
- * even for virtualhosts with multiple addresses, has an entry in this hash
- * table. There are extra buckets for _default_, and name-vhost entries.
- *
- * Note that after config time this is constant, so it is thread-safe.
- */
-static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
-
-/* dump out statistics about the hash function */
-/* #define IPHASH_STATISTICS */
-
-/* list of the _default_ servers */
-static ipaddr_chain *default_list;
-
-/* list of the NameVirtualHost addresses */
-static server_addr_rec *name_vhost_list;
-static server_addr_rec **name_vhost_list_tail;
-
-/*
- * How it's used:
- *
- * The ip address determines which chain in iphash_table is interesting, then
- * a comparison is done down that chain to find the first ipaddr_chain whose
- * sar matches the address:port pair.
- *
- * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
- *
- * Otherwise it's a name-vhost list, and the default is the server in the
- * ipaddr_chain record. We tuck away the ipaddr_chain record in the
- * conn_rec field vhost_lookup_data. Later on after the headers we get a
- * second chance, and we use the name_chain to figure out what name-vhost
- * matches the headers.
- *
- * If there was no ip address match in the iphash_table then do a lookup
- * in the default_list.
- *
- * How it's put together ... well you should be able to figure that out
- * from how it's used. Or something like that.
- */
-
-
-/* called at the beginning of the config */
-void ap_init_vhost_config(apr_pool_t *p)
-{
- memset(iphash_table, 0, sizeof(iphash_table));
- default_list = NULL;
- name_vhost_list = NULL;
- name_vhost_list_tail = &name_vhost_list;
-}
-
-
-/*
- * Parses a host of the form <address>[:port]
- * paddr is used to create a list in the order of input
- * **paddr is the ->next pointer of the last entry (or s->addrs)
- * *paddr is the variable used to keep track of **paddr between calls
- * port is the default port to assume
- */
-static const char *get_addresses(apr_pool_t *p, const char *w_,
- server_addr_rec ***paddr,
- apr_port_t default_port)
-{
- apr_sockaddr_t *my_addr;
- server_addr_rec *sar;
- char *w, *host, *scope_id;
- int wild_port;
- size_t wlen;
- apr_port_t port;
- apr_status_t rv;
-
- if (*w_ == '\0')
- return NULL;
-
- w = apr_pstrdup(p, w_);
- /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */
- wlen = strlen(w);
- if (wlen > 2 && w[wlen - 1] == '*' && w[wlen - 2] == ':') {
- w[wlen - 2] = '\0';
- wild_port = 1;
- }
- else {
- wild_port = 0;
- }
- rv = apr_parse_addr_port(&host, &scope_id, &port, w, p);
- if (rv != APR_SUCCESS) {
- return "The address or port is invalid";
- }
- if (scope_id) {
- return "Scope ids are not supported";
- }
- if (!port && !wild_port) {
- port = default_port;
- }
-
- if (strcmp(host, "*") == 0) {
- rv = apr_sockaddr_info_get(&my_addr, NULL, APR_INET, port, 0, p);
- my_addr->sa.sin.sin_addr.s_addr = htonl(INADDR_ANY);
- } else if (strcasecmp(host, "_default_") == 0
- || strcmp(host, "255.255.255.255") == 0) {
- rv = apr_sockaddr_info_get(&my_addr, NULL, APR_INET, port, 0, p);
- ap_assert(rv == APR_SUCCESS); /* must be bug or out of storage */
- my_addr->sa.sin.sin_addr.s_addr = DEFAULT_VHOST_ADDR;
- } else {
- rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
- "Cannot resolve host name %s --- ignoring!", host);
- return NULL;
- }
- }
-
- /* XXX Gotta go through *all* addresses for the host name!
- * Fix apr_sockaddr_info_get() to save them! */
-
- sar = apr_pcalloc(p, sizeof(server_addr_rec));
- **paddr = sar;
- *paddr = &sar->next;
- sar->host_addr = my_addr;
- sar->host_port = port;
- sar->virthost = host;
- return NULL;
-}
-
-
-/* parse the <VirtualHost> addresses */
-const char *ap_parse_vhost_addrs(apr_pool_t *p, const char *hostname, server_rec *s)
-{
- server_addr_rec **addrs;
- const char *err;
-
- /* start the list of addreses */
- addrs = &s->addrs;
- while (hostname[0]) {
- err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
- if (err) {
- *addrs = NULL;
- return err;
- }
- }
- /* terminate the list */
- *addrs = NULL;
- if (s->addrs) {
- if (s->addrs->host_port) {
- /* override the default port which is inherited from main_server */
- s->port = s->addrs->host_port;
- }
- }
- return NULL;
-}
-
-
-const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- /* use whatever port the main server has at this point */
- return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
- cmd->server->port);
-}
-
-
-/* hash apr_table_t statistics, keep this in here for the beta period so
- * we can find out if the hash function is ok
- */
-#ifdef IPHASH_STATISTICS
-static int iphash_compare(const void *a, const void *b)
-{
- return (*(const int *) b - *(const int *) a);
-}
-
-
-static void dump_iphash_statistics(server_rec *main_s)
-{
- unsigned count[IPHASH_TABLE_SIZE];
- int i;
- ipaddr_chain *src;
- unsigned total;
- char buf[HUGE_STRING_LEN];
- char *p;
-
- total = 0;
- for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
- count[i] = 0;
- for (src = iphash_table[i]; src; src = src->next) {
- ++count[i];
- if (i < IPHASH_TABLE_SIZE) {
- /* don't count the slop buckets in the total */
- ++total;
- }
- }
- }
- qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
- p = buf + apr_snprintf(buf, sizeof(buf),
- "iphash: total hashed = %u, avg chain = %u, "
- "chain lengths (count x len):",
- total, total / IPHASH_TABLE_SIZE);
- total = 1;
- for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {
- if (count[i - 1] != count[i]) {
- p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
- total, count[i - 1]);
- total = 1;
- }
- else {
- ++total;
- }
- }
- p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
- total, count[IPHASH_TABLE_SIZE - 1]);
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf);
-}
-#endif
-
-
-/* This hashing function is designed to get good distribution in the cases
- * where the server is handling entire "networks" of servers. i.e. a
- * whack of /24s. This is probably the most common configuration for
- * ISPs with large virtual servers.
- *
- * NOTE: This function is symmetric (i.e. collapses all 4 octets
- * into one), so machine byte order (big/little endianness) does not matter.
- *
- * Hash function provided by David Hankins.
- */
-static APR_INLINE unsigned hash_inaddr(unsigned key)
-{
- key ^= (key >> 16);
- return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
-}
-
-static APR_INLINE unsigned hash_addr(struct apr_sockaddr_t *sa)
-{
- unsigned key;
-
- /* The key is the last four bytes of the IP address.
- * For IPv4, this is the entire address, as always.
- * For IPv6, this is usually part of the MAC address.
- */
- key = *(unsigned *)((char *)sa->ipaddr_ptr + sa->ipaddr_len - 4);
- return hash_inaddr(key);
-}
-
-static ipaddr_chain *new_ipaddr_chain(apr_pool_t *p,
- server_rec *s, server_addr_rec *sar)
-{
- ipaddr_chain *new;
-
- new = apr_palloc(p, sizeof(*new));
- new->names = NULL;
- new->server = s;
- new->sar = sar;
- new->next = NULL;
- return new;
-}
-
-
-static name_chain *new_name_chain(apr_pool_t *p, server_rec *s, server_addr_rec *sar)
-{
- name_chain *new;
-
- new = apr_palloc(p, sizeof(*new));
- new->server = s;
- new->sar = sar;
- new->next = NULL;
- return new;
-}
-
-
-static APR_INLINE ipaddr_chain *find_ipaddr(apr_sockaddr_t *sa)
-{
- unsigned bucket;
- ipaddr_chain *trav;
-
- /* scan the hash apr_table_t for an exact match first */
- bucket = hash_addr(sa);
- for (trav = iphash_table[bucket]; trav; trav = trav->next) {
- server_addr_rec *sar = trav->sar;
- apr_sockaddr_t *cur = sar->host_addr;
-
- if (cur->sa.sin.sin_port == 0 ||
- sa->sa.sin.sin_port == 0 ||
- cur->sa.sin.sin_port == sa->sa.sin.sin_port) {
- if (cur->ipaddr_len == sa->ipaddr_len &&
- !memcmp(cur->ipaddr_ptr,
- sa->ipaddr_ptr,
- sa->ipaddr_len)) {
- return trav;
- }
- }
- }
- return NULL;
-}
-
-
-static ipaddr_chain *find_default_server(apr_port_t port)
-{
- server_addr_rec *sar;
- ipaddr_chain *trav;
-
- for (trav = default_list; trav; trav = trav->next) {
- sar = trav->sar;
- if (sar->host_port == 0 || sar->host_port == port) {
- /* match! */
- return trav;
- }
- }
- return NULL;
-}
-
-static void dump_a_vhost(apr_file_t *f, ipaddr_chain *ic)
-{
- name_chain *nc;
- int len;
- char buf[MAX_STRING_LEN];
- apr_sockaddr_t *ha = ic->sar->host_addr;
-
- if (ha->sa.sin.sin_family == APR_INET &&
- ha->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR) {
- len = apr_snprintf(buf, sizeof(buf), "_default_:%u",
- ic->sar->host_port);
- }
- else if (ha->sa.sin.sin_family == APR_INET &&
- ha->sa.sin.sin_addr.s_addr == INADDR_ANY) {
- len = apr_snprintf(buf, sizeof(buf), "*:%u",
- ic->sar->host_port);
- }
- else {
- len = apr_snprintf(buf, sizeof(buf), "%pI", ha);
- }
- if (ic->sar->host_port == 0) {
- buf[len-1] = '*';
- }
- if (ic->names == NULL) {
- apr_file_printf(f, "%-22s %s (%s:%u)\n", buf, ic->server->server_hostname,
- ic->server->defn_name, ic->server->defn_line_number);
- return;
- }
- apr_file_printf(f, "%-22s is a NameVirtualHost\n"
- "%8s default server %s (%s:%u)\n",
- buf, "", ic->server->server_hostname,
- ic->server->defn_name, ic->server->defn_line_number);
- for (nc = ic->names; nc; nc = nc->next) {
- if (nc->sar->host_port) {
- apr_file_printf(f, "%8s port %u ", "", nc->sar->host_port);
- }
- else {
- apr_file_printf(f, "%8s port * ", "");
- }
- apr_file_printf(f, "namevhost %s (%s:%u)\n", nc->server->server_hostname,
- nc->server->defn_name, nc->server->defn_line_number);
- }
-}
-
-static void dump_vhost_config(apr_file_t *f)
-{
- ipaddr_chain *ic;
- int i;
-
- apr_file_printf(f, "VirtualHost configuration:\n");
- for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
- for (ic = iphash_table[i]; ic; ic = ic->next) {
- dump_a_vhost(f, ic);
- }
- }
- if (default_list) {
- apr_file_printf(f, "wildcard NameVirtualHosts and _default_ servers:\n");
- for (ic = default_list; ic; ic = ic->next) {
- dump_a_vhost(f, ic);
- }
- }
-}
-
-/*
- * Two helper functions for ap_fini_vhost_config()
- */
-static int add_name_vhost_config(apr_pool_t *p, server_rec *main_s, server_rec *s,
- server_addr_rec *sar, ipaddr_chain *ic)
-{
- /* the first time we encounter a NameVirtualHost address
- * ic->server will be NULL, on subsequent encounters
- * ic->names will be non-NULL.
- */
- if (ic->names || ic->server == NULL) {
- name_chain *nc = new_name_chain(p, s, sar);
- nc->next = ic->names;
- ic->names = nc;
- ic->server = s;
- if (sar->host_port != ic->sar->host_port) {
- /* one of the two is a * port, the other isn't */
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
- "VirtualHost %s:%u -- mixing * "
- "ports and non-* ports with "
- "a NameVirtualHost address is not supported,"
- " proceeding with undefined results",
- sar->virthost, sar->host_port);
- }
- return 1;
- }
- else {
- /* IP-based vhosts are handled by the caller */
- return 0;
- }
-}
-
-static void remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic)
-{
- while (*pic) {
- ipaddr_chain *ic = *pic;
-
- if (ic->server == NULL) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
- "NameVirtualHost %s:%u has no VirtualHosts",
- ic->sar->virthost, ic->sar->host_port);
- *pic = ic->next;
- }
- else if (ic->names == NULL) {
- /* if server != NULL and names == NULL then we're done
- * looking at NameVirtualHosts
- */
- break;
- }
- else {
- pic = &ic->next;
- }
- }
-}
-
-/* compile the tables and such we need to do the run-time vhost lookups */
-AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s)
-{
- server_addr_rec *sar;
- int has_default_vhost_addr;
- server_rec *s;
- int i;
- ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
-
- /* terminate the name_vhost list */
- *name_vhost_list_tail = NULL;
-
- /* Main host first */
- s = main_s;
-
- if (!s->server_hostname) {
- s->server_hostname = ap_get_local_host(p);
- }
-
- /* initialize the tails */
- for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
- iphash_table_tail[i] = &iphash_table[i];
- }
-
- /* The first things to go into the hash apr_table_t are the NameVirtualHosts
- * Since name_vhost_list is in the same order that the directives
- * occured in the config file, we'll copy it in that order.
- */
- for (sar = name_vhost_list; sar; sar = sar->next) {
- unsigned bucket = hash_addr(sar->host_addr);
- ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
-
- if (sar->host_addr->sa.sin.sin_addr.s_addr != INADDR_ANY) {
- *iphash_table_tail[bucket] = ic;
- iphash_table_tail[bucket] = &ic->next;
- }
- else {
- /* A wildcard NameVirtualHost goes on the default_list so
- * that it can catch incoming requests on any address.
- */
- ic->next = default_list;
- default_list = ic;
- }
- /* Notice that what we've done is insert an ipaddr_chain with
- * both server and names NULL. This fact is used to spot name-
- * based vhosts in add_name_vhost_config().
- */
- }
-
- /* The next things to go into the hash apr_table_t are the virtual hosts
- * themselves. They're listed off of main_s->next in the reverse
- * order they occured in the config file, so we insert them at
- * the iphash_table_tail but don't advance the tail.
- */
-
- for (s = main_s->next; s; s = s->next) {
- has_default_vhost_addr = 0;
- for (sar = s->addrs; sar; sar = sar->next) {
- ipaddr_chain *ic;
-
- if (sar->host_addr->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR
- || sar->host_addr->sa.sin.sin_addr.s_addr == INADDR_ANY) {
- ic = find_default_server(sar->host_port);
- if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
- if (ic && ic->sar->host_port != 0) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
- 0, main_s, "_default_ VirtualHost overlap on port %u,"
- " the first has precedence", sar->host_port);
- }
- ic = new_ipaddr_chain(p, s, sar);
- ic->next = default_list;
- default_list = ic;
- }
- has_default_vhost_addr = 1;
- }
- else {
- /* see if it matches something we've already got */
- ic = find_ipaddr(sar->host_addr);
-
- if (!ic) {
- unsigned bucket = hash_addr(sar->host_addr);
-
- ic = new_ipaddr_chain(p, s, sar);
- ic->next = *iphash_table_tail[bucket];
- *iphash_table_tail[bucket] = ic;
- }
- else if (!add_name_vhost_config(p, main_s, s, sar, ic)) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
- "VirtualHost %s:%u overlaps with "
- "VirtualHost %s:%u, the first has precedence, "
- "perhaps you need a NameVirtualHost directive",
- sar->virthost, sar->host_port,
- ic->sar->virthost, ic->sar->host_port);
- ic->sar = sar;
- ic->server = s;
- }
- }
- }
-
- /* Ok now we want to set up a server_hostname if the user was
- * silly enough to forget one.
- * XXX: This is silly we should just crash and burn.
- */
- if (!s->server_hostname) {
- if (has_default_vhost_addr) {
- s->server_hostname = main_s->server_hostname;
- }
- else if (!s->addrs) {
- /* what else can we do? at this point this vhost has
- no configured name, probably because they used
- DNS in the VirtualHost statement. It's disabled
- anyhow by the host matching code. -djg */
- s->server_hostname =
- apr_pstrdup(p, "bogus_host_without_forward_dns");
- }
- else {
- apr_status_t rv;
- char *hostname;
-
- rv = apr_getnameinfo(&hostname, s->addrs->host_addr, 0);
- if (rv == APR_SUCCESS) {
- s->server_hostname = apr_pstrdup(p, hostname);
- }
- else {
- /* again, what can we do? They didn't specify a
- ServerName, and their DNS isn't working. -djg */
- char *ipaddr_str;
-
- apr_sockaddr_ip_get(&ipaddr_str, s->addrs->host_addr);
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, main_s,
- "Failed to resolve server name "
- "for %s (check DNS) -- or specify an explicit "
- "ServerName",
- ipaddr_str);
- s->server_hostname =
- apr_pstrdup(p, "bogus_host_without_reverse_dns");
- }
- }
- }
- }
-
- /* now go through and delete any NameVirtualHosts that didn't have any
- * hosts associated with them. Lamers.
- */
- for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
- remove_unused_name_vhosts(main_s, &iphash_table[i]);
- }
- remove_unused_name_vhosts(main_s, &default_list);
-
-#ifdef IPHASH_STATISTICS
- dump_iphash_statistics(main_s);
-#endif
- if (ap_exists_config_define("DUMP_VHOSTS")) {
- apr_file_t *thefile = NULL;
- apr_file_open_stderr(&thefile, p);
- dump_vhost_config(thefile);
- }
-}
-
-
-/*****************************************************************************
- * run-time vhost matching functions
- */
-
-/* Lowercase and remove any trailing dot and/or :port from the hostname,
- * and check that it is sane.
- *
- * In most configurations the exact syntax of the hostname isn't
- * important so strict sanity checking isn't necessary. However, in
- * mass hosting setups (using mod_vhost_alias or mod_rewrite) where
- * the hostname is interpolated into the filename, we need to be sure
- * that the interpolation doesn't expose parts of the filesystem.
- * We don't do strict RFC 952 / RFC 1123 syntax checking in order
- * to support iDNS and people who erroneously use underscores.
- * Instead we just check for filesystem metacharacters: directory
- * separators / and \ and sequences of more than one dot.
- */
-static void fix_hostname(request_rec *r)
-{
- char *host, *scope_id;
- char *dst;
- apr_port_t port;
- apr_status_t rv;
-
- rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
- if (rv != APR_SUCCESS || scope_id) {
- goto bad;
- }
-
- /* if the hostname is an IPv6 numeric address string, it was validated
- * already; otherwise, further validation is needed
- */
- if (r->hostname[0] != '[') {
- for (dst = host; *dst; dst++) {
- if (*dst == '.') {
- dst++;
- if (*dst == '.')
- goto bad;
- }
- else if (*dst == '/' || *dst == '\\') {
- goto bad;
- }
- }
- /* strip trailing gubbins */
- if (dst > host && dst[-1] == '.') {
- dst[-1] = '\0';
- }
- }
- r->hostname = host;
- return;
-
-bad:
- r->status = HTTP_BAD_REQUEST;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Client sent malformed Host header");
- return;
-}
-
-
-/* return 1 if host matches ServerName or ServerAliases */
-static int matches_aliases(server_rec *s, const char *host)
-{
- int i;
- apr_array_header_t *names;
-
- /* match ServerName */
- if (!strcasecmp(host, s->server_hostname)) {
- return 1;
- }
-
- /* search all the aliases from ServerAlias directive */
- names = s->names;
- if (names) {
- char **name = (char **) names->elts;
- for (i = 0; i < names->nelts; ++i) {
- if(!name[i]) continue;
- if (!strcasecmp(host, name[i]))
- return 1;
- }
- }
- names = s->wild_names;
- if (names) {
- char **name = (char **) names->elts;
- for (i = 0; i < names->nelts; ++i) {
- if(!name[i]) continue;
- if (!ap_strcasecmp_match(host, name[i]))
- return 1;
- }
- }
- return 0;
-}
-
-
-/* Suppose a request came in on the same socket as this r, and included
- * a header "Host: host:port", would it map to r->server? It's more
- * than just that though. When we do the normal matches for each request
- * we don't even bother considering Host: etc on non-namevirtualhosts,
- * we just call it a match. But here we require the host:port to match
- * the ServerName and/or ServerAliases.
- */
-AP_DECLARE(int) ap_matches_request_vhost(request_rec *r, const char *host,
- apr_port_t port)
-{
- server_rec *s;
- server_addr_rec *sar;
-
- s = r->server;
-
- /* search all the <VirtualHost> values */
- /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing
- * consider:
- *
- * NameVirtualHost 10.1.1.1
- * <VirtualHost 10.1.1.1>
- * ServerName v1
- * </VirtualHost>
- * <VirtualHost 10.1.1.1>
- * ServerName v2
- * </VirtualHost>
- *
- * Suppose r->server is v2, and we're asked to match "10.1.1.1". We'll say
- * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1
- * it would really go to v1.
- */
- for (sar = s->addrs; sar; sar = sar->next) {
- if ((sar->host_port == 0 || port == sar->host_port)
- && !strcasecmp(host, sar->virthost)) {
- return 1;
- }
- }
-
- /* the Port has to match now, because the rest don't have ports associated
- * with them. */
- if (port != s->port) {
- return 0;
- }
-
- return matches_aliases(s, host);
-}
-
-
-static void check_hostalias(request_rec *r)
-{
- /*
- * Even if the request has a Host: header containing a port we ignore
- * that port. We always use the physical port of the socket. There
- * are a few reasons for this:
- *
- * - the default of 80 or 443 for SSL is easier to handle this way
- * - there is less of a possibility of a security problem
- * - it simplifies the data structure
- * - the client may have no idea that a proxy somewhere along the way
- * translated the request to another ip:port
- * - except for the addresses from the VirtualHost line, none of the other
- * names we'll match have ports associated with them
- */
- const char *host = r->hostname;
- apr_port_t port;
- server_rec *s;
- server_rec *last_s;
- name_chain *src;
- apr_sockaddr_t *localsa;
-
- last_s = NULL;
- apr_socket_addr_get(&localsa, APR_LOCAL, r->connection->client_socket);
- apr_sockaddr_port_get(&port, localsa);
-
- /* Recall that the name_chain is a list of server_addr_recs, some of
- * whose ports may not match. Also each server may appear more than
- * once in the chain -- specifically, it will appear once for each
- * address from its VirtualHost line which matched. We only want to
- * do the full ServerName/ServerAlias comparisons once for each
- * server, fortunately we know that all the VirtualHost addresses for
- * a single server are adjacent to each other.
- */
-
- for (src = r->connection->vhost_lookup_data; src; src = src->next) {
- server_addr_rec *sar;
-
- /* We only consider addresses on the name_chain which have a matching
- * port
- */
- sar = src->sar;
- if (sar->host_port != 0 && port != sar->host_port) {
- continue;
- }
-
- s = src->server;
-
- /* does it match the virthost from the sar? */
- if (!strcasecmp(host, sar->virthost)) {
- goto found;
- }
-
- if (s == last_s) {
- /* we've already done ServerName and ServerAlias checks for this
- * vhost
- */
- continue;
- }
- last_s = s;
-
- if (matches_aliases(s, host)) {
- goto found;
- }
- }
- return;
-
-found:
- /* s is the first matching server, we're done */
- r->server = s;
-}
-
-
-static void check_serverpath(request_rec *r)
-{
- server_rec *s;
- server_rec *last_s;
- name_chain *src;
- apr_port_t port;
- apr_sockaddr_t *localsa;
-
- apr_socket_addr_get(&localsa, APR_LOCAL, r->connection->client_socket);
- apr_sockaddr_port_get(&port, localsa);
-
- /*
- * This is in conjunction with the ServerPath code in http_core, so we
- * get the right host attached to a non- Host-sending request.
- *
- * See the comment in check_hostalias about how each vhost can be
- * listed multiple times.
- */
-
- last_s = NULL;
- for (src = r->connection->vhost_lookup_data; src; src = src->next) {
- /* We only consider addresses on the name_chain which have a matching
- * port
- */
- if (src->sar->host_port != 0 && port != src->sar->host_port) {
- continue;
- }
-
- s = src->server;
- if (s == last_s) {
- continue;
- }
- last_s = s;
-
- if (s->path && !strncmp(r->uri, s->path, s->pathlen) &&
- (s->path[s->pathlen - 1] == '/' ||
- r->uri[s->pathlen] == '/' ||
- r->uri[s->pathlen] == '\0')) {
- r->server = s;
- return;
- }
- }
-}
-
-
-void ap_update_vhost_from_headers(request_rec *r)
-{
- /* must set this for HTTP/1.1 support */
- if (r->hostname || (r->hostname = apr_table_get(r->headers_in, "Host"))) {
- fix_hostname(r);
- if (r->status != HTTP_OK)
- return;
- }
- /* check if we tucked away a name_chain */
- if (r->connection->vhost_lookup_data) {
- if (r->hostname)
- check_hostalias(r);
- else
- check_serverpath(r);
- }
-}
-
-
-/* Called for a new connection which has a known local_addr. Note that the
- * new connection is assumed to have conn->server == main server.
- */
-void ap_update_vhost_given_ip(conn_rec *conn)
-{
- ipaddr_chain *trav;
- apr_port_t port;
-
- /* scan the hash apr_table_t for an exact match first */
- trav = find_ipaddr(conn->local_addr);
- if (trav) {
- /* save the name_chain for later in case this is a name-vhost */
- conn->vhost_lookup_data = trav->names;
- conn->base_server = trav->server;
- return;
- }
-
- /* maybe there's a default server or wildcard name-based vhost
- * matching this port
- */
- apr_sockaddr_port_get(&port, conn->local_addr);
- trav = find_default_server(port);
- if (trav) {
- conn->vhost_lookup_data = trav->names;
- conn->base_server = trav->server;
- return;
- }
-
- /* otherwise we're stuck with just the main server
- * and no name-based vhosts
- */
- conn->vhost_lookup_data = NULL;
-}