summaryrefslogtreecommitdiffstats
path: root/rubbos/app/httpd-2.0.64/modules/generators
diff options
context:
space:
mode:
authorhongbotian <hongbo.tianhongbo@huawei.com>2015-11-30 01:45:08 -0500
committerhongbotian <hongbo.tianhongbo@huawei.com>2015-11-30 01:45:08 -0500
commite8ec7aa8e38a93f5b034ac74cebce5de23710317 (patch)
treeaa031937bf856c1f8d6ad7877b8d2cb0224da5ef /rubbos/app/httpd-2.0.64/modules/generators
parentcc40af334e619bb549038238507407866f774f8f (diff)
upload http
JIRA: BOTTLENECK-10 Change-Id: I7598427ff904df438ce77c2819ee48ac75ffa8da Signed-off-by: hongbotian <hongbo.tianhongbo@huawei.com>
Diffstat (limited to 'rubbos/app/httpd-2.0.64/modules/generators')
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.deps0
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.indent.pro54
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.abin0 -> 33444 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.obin0 -> 33296 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.abin0 -> 150722 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.obin0 -> 150568 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.abin0 -> 153612 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.obin0 -> 153464 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.abin0 -> 97328 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.obin0 -> 97120 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/Makefile8
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/Makefile.in3
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/NWGNUinfo248
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/NWGNUmakefile247
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/NWGNUstatus248
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/config5.m466
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_asis.c145
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_asis.dsp128
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_asis.exp1
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_asis.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_asis.lo12
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_asis.obin0 -> 33296 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.c2252
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.dsp128
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.exp1
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.lo12
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.obin0 -> 150568 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.c1235
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.dsp132
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.exp1
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.h62
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.c1744
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.exp1
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.lo12
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.obin0 -> 153464 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_info.c533
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_info.dsp128
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_info.exp1
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_status.c857
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_status.dsp128
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_status.exp1
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_status.h54
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_status.la35
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_status.lo12
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_status.obin0 -> 97120 bytes
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.c138
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.h23
-rw-r--r--rubbos/app/httpd-2.0.64/modules/generators/modules.mk11
54 files changed, 8906 insertions, 0 deletions
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.deps b/rubbos/app/httpd-2.0.64/modules/generators/.deps
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.deps
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.indent.pro b/rubbos/app/httpd-2.0.64/modules/generators/.indent.pro
new file mode 100644
index 00000000..a9fbe9f9
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.indent.pro
@@ -0,0 +1,54 @@
+-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/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.a b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.a
new file mode 100644
index 00000000..f7606c14
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.a
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.la b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.la
new file mode 100644
index 00000000..f3cb430d
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.la
@@ -0,0 +1,35 @@
+# mod_asis.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_asis.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_asis.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.o b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.o
new file mode 100644
index 00000000..acca9866
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.a b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.a
new file mode 100644
index 00000000..e4afe274
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.a
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.la b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.la
new file mode 100644
index 00000000..139298d2
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.la
@@ -0,0 +1,35 @@
+# mod_autoindex.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_autoindex.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_autoindex.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.o b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.o
new file mode 100644
index 00000000..08725d05
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.a b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.a
new file mode 100644
index 00000000..80394ff9
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.a
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.la b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.la
new file mode 100644
index 00000000..7528f2d9
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.la
@@ -0,0 +1,35 @@
+# mod_cgid.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_cgid.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_cgid.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.o b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.o
new file mode 100644
index 00000000..ffbaef81
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.a b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.a
new file mode 100644
index 00000000..00fe8005
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.a
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.la b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.la
new file mode 100644
index 00000000..fc5f7173
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.la
@@ -0,0 +1,35 @@
+# mod_status.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_status.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_status.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.o b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.o
new file mode 100644
index 00000000..107ccfef
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/Makefile b/rubbos/app/httpd-2.0.64/modules/generators/Makefile
new file mode 100644
index 00000000..16be1a0d
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/Makefile
@@ -0,0 +1,8 @@
+top_srcdir = /bottlenecks/rubbos/app/httpd-2.0.64
+top_builddir = /bottlenecks/rubbos/app/httpd-2.0.64
+srcdir = /bottlenecks/rubbos/app/httpd-2.0.64/modules/generators
+builddir = /bottlenecks/rubbos/app/httpd-2.0.64/modules/generators
+VPATH = /bottlenecks/rubbos/app/httpd-2.0.64/modules/generators
+
+include $(top_srcdir)/build/special.mk
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/Makefile.in b/rubbos/app/httpd-2.0.64/modules/generators/Makefile.in
new file mode 100644
index 00000000..167b343d
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/Makefile.in
@@ -0,0 +1,3 @@
+
+include $(top_srcdir)/build/special.mk
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/NWGNUinfo b/rubbos/app/httpd-2.0.64/modules/generators/NWGNUinfo
new file mode 100644
index 00000000..eb76803f
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/NWGNUinfo
@@ -0,0 +1,248 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\build\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APRUTIL)/include \
+ $(AP_WORK)/include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = info
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache $(VERSION_STR) Info Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Info Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _LibCPrelude
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _LibCPostlude
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/info.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_info.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ libcpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ aprlib \
+ libc \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @$(APR)/aprlib.imp \
+ @$(NWOS)/httpd.imp \
+ @libc.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ info_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\build\NWGNUtail.inc
+
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/NWGNUmakefile b/rubbos/app/httpd-2.0.64/modules/generators/NWGNUmakefile
new file mode 100644
index 00000000..7f7d343b
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/NWGNUmakefile
@@ -0,0 +1,247 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(AP_WORK)\build\NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/info.nlm \
+ $(OBJDIR)/status.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\*.nlm $(INSTALL)\Apache2\modules\*.*
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\build\NWGNUtail.inc
+
+
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/NWGNUstatus b/rubbos/app/httpd-2.0.64/modules/generators/NWGNUstatus
new file mode 100644
index 00000000..01cbef5a
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/NWGNUstatus
@@ -0,0 +1,248 @@
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# Get the 'head' of the build environment if necessary. This includes default
+# targets and paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(AP_WORK)\build\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APRUTIL)/include \
+ $(AP_WORK)/include \
+ $(NWOS) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = status
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache $(VERSION_STR) Status Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = Status Module
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _LibCPrelude
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _LibCPostlude
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/status.nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/mod_status.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ libcpre.o \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ aprlib \
+ libc \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @$(APR)/aprlib.imp \
+ @$(NWOS)/httpd.imp \
+ @libc.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ status_module \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(AP_WORK)\build\NWGNUtail.inc
+
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/config5.m4 b/rubbos/app/httpd-2.0.64/modules/generators/config5.m4
new file mode 100644
index 00000000..f4afb7f1
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/config5.m4
@@ -0,0 +1,66 @@
+dnl modules enabled in this directory by default
+
+dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
+
+APACHE_MODPATH_INIT(generators)
+
+APACHE_MODULE(status, process/thread monitoring, , , yes)
+APACHE_MODULE(autoindex, directory listing, , , yes)
+APACHE_MODULE(asis, as-is filetypes, , , yes)
+APACHE_MODULE(info, server information, , , most)
+APACHE_MODULE(suexec, set uid and gid for spawned processes, , , no, [
+ other_targets=suexec ] )
+
+APR_ADDTO(LT_LDFLAGS,-export-dynamic)
+
+if test "$apache_cv_mpm" = "worker" -o "$apache_cv_mpm" = "perchild"; then
+# if we are using a threaded MPM, we will get better performance with
+# mod_cgid, so make it the default.
+ APACHE_MODULE(cgid, CGI scripts, , , yes, [
+ case $host in
+ *-solaris2*)
+ case `uname -r` in
+ 5.10)
+ dnl Does the system have the appropriate patches?
+ case `uname -p` in
+ i386)
+ patch_id="120665"
+ ;;
+ sparc)
+ patch_id="120664"
+ ;;
+ *)
+ AC_MSG_WARN([Unknown platform])
+ patch_id="120664"
+ ;;
+ esac
+ AC_MSG_CHECKING([for Solaris patch $patch_id])
+ showrev -p | grep "$patch_id" >/dev/null 2>&1
+ if test $? -eq 1; then
+ dnl Solaris 11 (next release) as of snv_19 doesn't have this problem.
+ dnl It may be possible to use /kernel/drv/tl from later releases.
+ AC_MSG_ERROR([Please apply either patch # 120664 (Sparc) or # 120665 (x86).
+Without these patches, mod_cgid is non-functional on Solaris 10 due to an OS
+bug with AF_UNIX sockets.
+If you can not apply these patches, you can do one of the following:
+ - run configure with --disable-cgid
+ - switch to the prefork MPM
+For more info: <http://issues.apache.org/bugzilla/show_bug.cgi?id=34264>])
+ else
+ AC_MSG_RESULT(yes)
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ])
+ APACHE_MODULE(cgi, CGI scripts, , , no)
+else
+# if we are using a non-threaded MPM, it makes little sense to use
+# mod_cgid, and it just opens up holes we don't need. Make mod_cgi the
+# default
+ APACHE_MODULE(cgi, CGI scripts, , , yes)
+ APACHE_MODULE(cgid, CGI scripts, , , no)
+fi
+
+APACHE_MODPATH_FINISH
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.c b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.c
new file mode 100644
index 00000000..a5c65b47
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.c
@@ -0,0 +1,145 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#include "ap_config.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "util_script.h"
+#include "http_main.h"
+#include "http_request.h"
+
+#include "mod_core.h"
+
+#define ASIS_MAGIC_TYPE "httpd/send-as-is"
+
+static int asis_handler(request_rec *r)
+{
+ conn_rec *c = r->connection;
+ apr_file_t *f = NULL;
+ apr_status_t rv;
+ const char *location;
+
+ if(strcmp(r->handler,ASIS_MAGIC_TYPE) && strcmp(r->handler,"send-as-is"))
+ return DECLINED;
+
+ r->allowed |= (AP_METHOD_BIT << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+ if (r->finfo.filetype == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "File does not exist: %s", r->filename);
+ return HTTP_NOT_FOUND;
+ }
+
+ if ((rv = apr_file_open(&f, r->filename, APR_READ,
+ APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "file permissions deny server access: %s", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+
+ ap_scan_script_header_err(r, f, NULL);
+ location = apr_table_get(r->headers_out, "Location");
+
+ if (location && location[0] == '/' &&
+ ((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
+
+ apr_file_close(f);
+
+ /* Internal redirect -- fake-up a pseudo-request */
+ r->status = HTTP_OK;
+
+ /* This redirect needs to be a GET no matter what the original
+ * method was.
+ */
+ r->method = apr_pstrdup(r->pool, "GET");
+ r->method_number = M_GET;
+
+ ap_internal_redirect_handler(location, r);
+ return OK;
+ }
+
+ if (!r->header_only) {
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ apr_off_t pos = 0;
+
+ rv = apr_file_seek(f, APR_CUR, &pos);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "mod_asis: failed to find end-of-headers position "
+ "for %s", r->filename);
+ apr_file_close(f);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+#if APR_HAS_LARGE_FILES
+ if (r->finfo.size - pos > AP_MAX_SENDFILE) {
+ /* APR_HAS_LARGE_FILES issue; must split into mutiple buckets,
+ * no greater than MAX(apr_size_t), and more granular than that
+ * in case the brigade code/filters attempt to read it directly.
+ */
+ apr_off_t fsize = r->finfo.size - pos;
+ b = apr_bucket_file_create(f, pos, AP_MAX_SENDFILE,
+ r->pool, c->bucket_alloc);
+ while (fsize > AP_MAX_SENDFILE) {
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ apr_bucket_copy(b, &b);
+ b->start += AP_MAX_SENDFILE;
+ fsize -= AP_MAX_SENDFILE;
+ }
+ b->length = (apr_size_t)fsize; /* Resize just the last bucket */
+ }
+ else
+#endif
+ b = apr_bucket_file_create(f, pos, (apr_size_t) (r->finfo.size - pos),
+ r->pool, c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ rv = ap_pass_brigade(r->output_filters, bb);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "mod_asis: ap_pass_brigade failed for file %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+ else {
+ apr_file_close(f);
+ }
+
+ return OK;
+}
+
+static void register_hooks(apr_pool_t *p)
+{
+ ap_hook_handler(asis_handler,NULL,NULL,APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA asis_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ NULL, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ NULL, /* command apr_table_t */
+ register_hooks /* register hooks */
+};
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.dsp b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.dsp
new file mode 100644
index 00000000..77fdafd3
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.dsp
@@ -0,0 +1,128 @@
+# Microsoft Developer Studio Project File - Name="mod_asis" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_asis - 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 "mod_asis.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 "mod_asis.mak" CFG="mod_asis - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_asis - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_asis - 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)" == "mod_asis - 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 /Zi /O2 /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_asis_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:"Release/mod_asis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_asis.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Release/mod_asis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_asis.so /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_asis - 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 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_asis_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_asis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_asis.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_asis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_asis.so
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_asis - Win32 Release"
+# Name "mod_asis - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_asis.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_asis.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\win32ver.awk
+
+!IF "$(CFG)" == "mod_asis - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_asis.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_asis.so "asis_module for Apache" ../../include/ap_release.h > .\mod_asis.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "mod_asis - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_asis.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_asis.so "asis_module for Apache" ../../include/ap_release.h > .\mod_asis.rc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.exp b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.exp
new file mode 100644
index 00000000..4f347d92
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.exp
@@ -0,0 +1 @@
+asis_module
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.la b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.la
new file mode 100644
index 00000000..f3cb430d
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.la
@@ -0,0 +1,35 @@
+# mod_asis.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_asis.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_asis.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.lo b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.lo
new file mode 100644
index 00000000..7eeba69a
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.lo
@@ -0,0 +1,12 @@
+# mod_asis.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object='.libs/mod_asis.o'
+
+# Name of the non-PIC object.
+non_pic_object='mod_asis.o'
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.o b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.o
new file mode 100644
index 00000000..acca9866
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.c b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.c
new file mode 100644
index 00000000..f98f12f3
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.c
@@ -0,0 +1,2252 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * mod_autoindex.c: Handles the on-the-fly html index generation
+ *
+ * Rob McCool
+ * 3/23/93
+ *
+ * Adapted to Apache by rst.
+ *
+ * Version sort added by Martin Pool <mbp@humbug.org.au>.
+ */
+
+#include "apr_strings.h"
+#include "apr_fnmatch.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "ap_config.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "util_script.h"
+
+#include "mod_core.h"
+
+module AP_MODULE_DECLARE_DATA autoindex_module;
+
+/****************************************************************
+ *
+ * Handling configuration directives...
+ */
+
+#define NO_OPTIONS (1 << 0) /* Indexing options */
+#define ICONS_ARE_LINKS (1 << 1)
+#define SCAN_HTML_TITLES (1 << 2)
+#define SUPPRESS_ICON (1 << 3)
+#define SUPPRESS_LAST_MOD (1 << 4)
+#define SUPPRESS_SIZE (1 << 5)
+#define SUPPRESS_DESC (1 << 6)
+#define SUPPRESS_PREAMBLE (1 << 7)
+#define SUPPRESS_COLSORT (1 << 8)
+#define SUPPRESS_RULES (1 << 9)
+#define FOLDERS_FIRST (1 << 10)
+#define VERSION_SORT (1 << 11)
+#define TRACK_MODIFIED (1 << 12)
+#define FANCY_INDEXING (1 << 13)
+#define TABLE_INDEXING (1 << 14)
+#define IGNORE_CLIENT (1 << 15)
+#define IGNORE_CASE (1 << 16)
+#define EMIT_XHTML (1 << 17)
+
+#define K_NOADJUST 0
+#define K_ADJUST 1
+#define K_UNSET 2
+
+/*
+ * Define keys for sorting.
+ */
+#define K_NAME 'N' /* Sort by file name (default) */
+#define K_LAST_MOD 'M' /* Last modification date */
+#define K_SIZE 'S' /* Size (absolute, not as displayed) */
+#define K_DESC 'D' /* Description */
+#define K_VALID "NMSD" /* String containing _all_ valid K_ opts */
+
+#define D_ASCENDING 'A'
+#define D_DESCENDING 'D'
+#define D_VALID "AD" /* String containing _all_ valid D_ opts */
+
+/*
+ * These are the dimensions of the default icons supplied with Apache.
+ */
+#define DEFAULT_ICON_WIDTH 20
+#define DEFAULT_ICON_HEIGHT 22
+
+/*
+ * Other default dimensions.
+ */
+#define DEFAULT_NAME_WIDTH 23
+#define DEFAULT_DESC_WIDTH 23
+
+struct item {
+ char *type;
+ char *apply_to;
+ char *apply_path;
+ char *data;
+};
+
+typedef struct ai_desc_t {
+ char *pattern;
+ char *description;
+ int full_path;
+ int wildcards;
+} ai_desc_t;
+
+typedef struct autoindex_config_struct {
+
+ char *default_icon;
+ apr_int32_t opts;
+ apr_int32_t incremented_opts;
+ apr_int32_t decremented_opts;
+ int name_width;
+ int name_adjust;
+ int desc_width;
+ int desc_adjust;
+ int icon_width;
+ int icon_height;
+ char default_keyid;
+ char default_direction;
+
+ apr_array_header_t *icon_list;
+ apr_array_header_t *alt_list;
+ apr_array_header_t *desc_list;
+ apr_array_header_t *ign_list;
+ apr_array_header_t *hdr_list;
+ apr_array_header_t *rdme_list;
+
+ char *ctype;
+ char *charset;
+} autoindex_config_rec;
+
+static char c_by_encoding, c_by_type, c_by_path;
+
+#define BY_ENCODING &c_by_encoding
+#define BY_TYPE &c_by_type
+#define BY_PATH &c_by_path
+
+/*
+ * This routine puts the standard HTML header at the top of the index page.
+ * We include the DOCTYPE because we may be using features therefrom (i.e.,
+ * HEIGHT and WIDTH attributes on the icons if we're FancyIndexing).
+ */
+static void emit_preamble(request_rec *r, int xhtml, const char *title)
+{
+ ap_rvputs(r, xhtml ? DOCTYPE_XHTML_1_0T : DOCTYPE_HTML_3_2,
+ "<html>\n <head>\n <title>Index of ", title,
+ "</title>\n </head>\n <body>\n", NULL);
+}
+
+static void push_item(apr_array_header_t *arr, char *type, const char *to,
+ const char *path, const char *data)
+{
+ struct item *p = (struct item *) apr_array_push(arr);
+
+ if (!to) {
+ to = "";
+ }
+ if (!path) {
+ path = "";
+ }
+
+ p->type = type;
+ p->data = data ? apr_pstrdup(arr->pool, data) : NULL;
+ p->apply_path = apr_pstrcat(arr->pool, path, "*", NULL);
+
+ if ((type == BY_PATH) && (!ap_is_matchexp(to))) {
+ p->apply_to = apr_pstrcat(arr->pool, "*", to, NULL);
+ }
+ else if (to) {
+ p->apply_to = apr_pstrdup(arr->pool, to);
+ }
+ else {
+ p->apply_to = NULL;
+ }
+}
+
+static const char *add_alt(cmd_parms *cmd, void *d, const char *alt,
+ const char *to)
+{
+ if (cmd->info == BY_PATH) {
+ if (!strcmp(to, "**DIRECTORY**")) {
+ to = "^^DIRECTORY^^";
+ }
+ }
+ if (cmd->info == BY_ENCODING) {
+ char *tmp = apr_pstrdup(cmd->pool, to);
+ ap_str_tolower(tmp);
+ to = tmp;
+ }
+
+ push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to,
+ cmd->path, alt);
+ return NULL;
+}
+
+static const char *add_icon(cmd_parms *cmd, void *d, const char *icon,
+ const char *to)
+{
+ char *iconbak = apr_pstrdup(cmd->pool, icon);
+
+ if (icon[0] == '(') {
+ char *alt;
+ char *cl = strchr(iconbak, ')');
+
+ if (cl == NULL) {
+ return "missing closing paren";
+ }
+ alt = ap_getword_nc(cmd->pool, &iconbak, ',');
+ *cl = '\0'; /* Lose closing paren */
+ add_alt(cmd, d, &alt[1], to);
+ }
+ if (cmd->info == BY_PATH) {
+ if (!strcmp(to, "**DIRECTORY**")) {
+ to = "^^DIRECTORY^^";
+ }
+ }
+ if (cmd->info == BY_ENCODING) {
+ char *tmp = apr_pstrdup(cmd->pool, to);
+ ap_str_tolower(tmp);
+ to = tmp;
+ }
+
+ push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to,
+ cmd->path, iconbak);
+ return NULL;
+}
+
+/*
+ * Add description text for a filename pattern. If the pattern has
+ * wildcards already (or we need to add them), add leading and
+ * trailing wildcards to it to ensure substring processing. If the
+ * pattern contains a '/' anywhere, force wildcard matching mode,
+ * add a slash to the prefix so that "bar/bletch" won't be matched
+ * by "foobar/bletch", and make a note that there's a delimiter;
+ * the matching routine simplifies to just the actual filename
+ * whenever it can. This allows definitions in parent directories
+ * to be made for files in subordinate ones using relative paths.
+ */
+
+/*
+ * Absent a strcasestr() function, we have to force wildcards on
+ * systems for which "AAA" and "aaa" mean the same file.
+ */
+#ifdef CASE_BLIND_FILESYSTEM
+#define WILDCARDS_REQUIRED 1
+#else
+#define WILDCARDS_REQUIRED 0
+#endif
+
+static const char *add_desc(cmd_parms *cmd, void *d, const char *desc,
+ const char *to)
+{
+ autoindex_config_rec *dcfg = (autoindex_config_rec *) d;
+ ai_desc_t *desc_entry;
+ char *prefix = "";
+
+ desc_entry = (ai_desc_t *) apr_array_push(dcfg->desc_list);
+ desc_entry->full_path = (ap_strchr_c(to, '/') == NULL) ? 0 : 1;
+ desc_entry->wildcards = (WILDCARDS_REQUIRED
+ || desc_entry->full_path
+ || apr_fnmatch_test(to));
+ if (desc_entry->wildcards) {
+ prefix = desc_entry->full_path ? "*/" : "*";
+ desc_entry->pattern = apr_pstrcat(dcfg->desc_list->pool,
+ prefix, to, "*", NULL);
+ }
+ else {
+ desc_entry->pattern = apr_pstrdup(dcfg->desc_list->pool, to);
+ }
+ desc_entry->description = apr_pstrdup(dcfg->desc_list->pool, desc);
+ return NULL;
+}
+
+static const char *add_ignore(cmd_parms *cmd, void *d, const char *ext)
+{
+ push_item(((autoindex_config_rec *) d)->ign_list, 0, ext, cmd->path, NULL);
+ return NULL;
+}
+
+static const char *add_header(cmd_parms *cmd, void *d, const char *name)
+{
+ push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path,
+ name);
+ return NULL;
+}
+
+static const char *add_readme(cmd_parms *cmd, void *d, const char *name)
+{
+ push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path,
+ name);
+ return NULL;
+}
+
+static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
+{
+ char *w;
+ apr_int32_t opts;
+ apr_int32_t opts_add;
+ apr_int32_t opts_remove;
+ char action;
+ autoindex_config_rec *d_cfg = (autoindex_config_rec *) d;
+
+ opts = d_cfg->opts;
+ opts_add = d_cfg->incremented_opts;
+ opts_remove = d_cfg->decremented_opts;
+ while (optstr[0]) {
+ int option = 0;
+
+ w = ap_getword_conf(cmd->pool, &optstr);
+ if ((*w == '+') || (*w == '-')) {
+ action = *(w++);
+ }
+ else {
+ action = '\0';
+ }
+ if (!strcasecmp(w, "FancyIndexing")) {
+ option = FANCY_INDEXING;
+ }
+ else if (!strcasecmp(w, "FoldersFirst")) {
+ option = FOLDERS_FIRST;
+ }
+ else if (!strcasecmp(w, "HTMLTable")) {
+ option = TABLE_INDEXING;
+ }
+ else if (!strcasecmp(w, "IconsAreLinks")) {
+ option = ICONS_ARE_LINKS;
+ }
+ else if (!strcasecmp(w, "IgnoreCase")) {
+ option = IGNORE_CASE;
+ }
+ else if (!strcasecmp(w, "IgnoreClient")) {
+ option = IGNORE_CLIENT;
+ }
+ else if (!strcasecmp(w, "ScanHTMLTitles")) {
+ option = SCAN_HTML_TITLES;
+ }
+ else if (!strcasecmp(w, "SuppressColumnSorting")) {
+ option = SUPPRESS_COLSORT;
+ }
+ else if (!strcasecmp(w, "SuppressDescription")) {
+ option = SUPPRESS_DESC;
+ }
+ else if (!strcasecmp(w, "SuppressHTMLPreamble")) {
+ option = SUPPRESS_PREAMBLE;
+ }
+ else if (!strcasecmp(w, "SuppressIcon")) {
+ option = SUPPRESS_ICON;
+ }
+ else if (!strcasecmp(w, "SuppressLastModified")) {
+ option = SUPPRESS_LAST_MOD;
+ }
+ else if (!strcasecmp(w, "SuppressSize")) {
+ option = SUPPRESS_SIZE;
+ }
+ else if (!strcasecmp(w, "SuppressRules")) {
+ option = SUPPRESS_RULES;
+ }
+ else if (!strcasecmp(w, "TrackModified")) {
+ option = TRACK_MODIFIED;
+ }
+ else if (!strcasecmp(w, "VersionSort")) {
+ option = VERSION_SORT;
+ }
+ else if (!strcasecmp(w, "XHTML")) {
+ option = EMIT_XHTML;
+ }
+ else if (!strcasecmp(w, "None")) {
+ if (action != '\0') {
+ return "Cannot combine '+' or '-' with 'None' keyword";
+ }
+ opts = NO_OPTIONS;
+ opts_add = 0;
+ opts_remove = 0;
+ }
+ else if (!strcasecmp(w, "IconWidth")) {
+ if (action != '-') {
+ d_cfg->icon_width = DEFAULT_ICON_WIDTH;
+ }
+ else {
+ d_cfg->icon_width = 0;
+ }
+ }
+ else if (!strncasecmp(w, "IconWidth=", 10)) {
+ if (action == '-') {
+ return "Cannot combine '-' with IconWidth=n";
+ }
+ d_cfg->icon_width = atoi(&w[10]);
+ }
+ else if (!strcasecmp(w, "IconHeight")) {
+ if (action != '-') {
+ d_cfg->icon_height = DEFAULT_ICON_HEIGHT;
+ }
+ else {
+ d_cfg->icon_height = 0;
+ }
+ }
+ else if (!strncasecmp(w, "IconHeight=", 11)) {
+ if (action == '-') {
+ return "Cannot combine '-' with IconHeight=n";
+ }
+ d_cfg->icon_height = atoi(&w[11]);
+ }
+ else if (!strcasecmp(w, "NameWidth")) {
+ if (action != '-') {
+ return "NameWidth with no value may only appear as "
+ "'-NameWidth'";
+ }
+ d_cfg->name_width = DEFAULT_NAME_WIDTH;
+ d_cfg->name_adjust = K_NOADJUST;
+ }
+ else if (!strncasecmp(w, "NameWidth=", 10)) {
+ if (action == '-') {
+ return "Cannot combine '-' with NameWidth=n";
+ }
+ if (w[10] == '*') {
+ d_cfg->name_adjust = K_ADJUST;
+ }
+ else {
+ int width = atoi(&w[10]);
+
+ if (width && (width < 5)) {
+ return "NameWidth value must be greater than 5";
+ }
+ d_cfg->name_width = width;
+ d_cfg->name_adjust = K_NOADJUST;
+ }
+ }
+ else if (!strcasecmp(w, "DescriptionWidth")) {
+ if (action != '-') {
+ return "DescriptionWidth with no value may only appear as "
+ "'-DescriptionWidth'";
+ }
+ d_cfg->desc_width = DEFAULT_DESC_WIDTH;
+ d_cfg->desc_adjust = K_NOADJUST;
+ }
+ else if (!strncasecmp(w, "DescriptionWidth=", 17)) {
+ if (action == '-') {
+ return "Cannot combine '-' with DescriptionWidth=n";
+ }
+ if (w[17] == '*') {
+ d_cfg->desc_adjust = K_ADJUST;
+ }
+ else {
+ int width = atoi(&w[17]);
+
+ if (width && (width < 12)) {
+ return "DescriptionWidth value must be greater than 12";
+ }
+ d_cfg->desc_width = width;
+ d_cfg->desc_adjust = K_NOADJUST;
+ }
+ }
+ else if (!strncasecmp(w, "Type=", 5)) {
+ d_cfg->ctype = apr_pstrdup(cmd->pool, &w[5]);
+ }
+ else if (!strncasecmp(w, "Charset=", 8)) {
+ d_cfg->charset = apr_pstrdup(cmd->pool, &w[8]);
+ }
+ else {
+ return "Invalid directory indexing option";
+ }
+ if (action == '\0') {
+ opts |= option;
+ opts_add = 0;
+ opts_remove = 0;
+ }
+ else if (action == '+') {
+ opts_add |= option;
+ opts_remove &= ~option;
+ }
+ else {
+ opts_remove |= option;
+ opts_add &= ~option;
+ }
+ }
+ if ((opts & NO_OPTIONS) && (opts & ~NO_OPTIONS)) {
+ return "Cannot combine other IndexOptions keywords with 'None'";
+ }
+ d_cfg->incremented_opts = opts_add;
+ d_cfg->decremented_opts = opts_remove;
+ d_cfg->opts = opts;
+ return NULL;
+}
+
+static const char *set_default_order(cmd_parms *cmd, void *m,
+ const char *direction, const char *key)
+{
+ autoindex_config_rec *d_cfg = (autoindex_config_rec *) m;
+
+ if (!strcasecmp(direction, "Ascending")) {
+ d_cfg->default_direction = D_ASCENDING;
+ }
+ else if (!strcasecmp(direction, "Descending")) {
+ d_cfg->default_direction = D_DESCENDING;
+ }
+ else {
+ return "First keyword must be 'Ascending' or 'Descending'";
+ }
+
+ if (!strcasecmp(key, "Name")) {
+ d_cfg->default_keyid = K_NAME;
+ }
+ else if (!strcasecmp(key, "Date")) {
+ d_cfg->default_keyid = K_LAST_MOD;
+ }
+ else if (!strcasecmp(key, "Size")) {
+ d_cfg->default_keyid = K_SIZE;
+ }
+ else if (!strcasecmp(key, "Description")) {
+ d_cfg->default_keyid = K_DESC;
+ }
+ else {
+ return "Second keyword must be 'Name', 'Date', 'Size', or "
+ "'Description'";
+ }
+
+ return NULL;
+}
+
+#define DIR_CMD_PERMS OR_INDEXES
+
+static const command_rec autoindex_cmds[] =
+{
+ AP_INIT_ITERATE2("AddIcon", add_icon, BY_PATH, DIR_CMD_PERMS,
+ "an icon URL followed by one or more filenames"),
+ AP_INIT_ITERATE2("AddIconByType", add_icon, BY_TYPE, DIR_CMD_PERMS,
+ "an icon URL followed by one or more MIME types"),
+ AP_INIT_ITERATE2("AddIconByEncoding", add_icon, BY_ENCODING, DIR_CMD_PERMS,
+ "an icon URL followed by one or more content encodings"),
+ AP_INIT_ITERATE2("AddAlt", add_alt, BY_PATH, DIR_CMD_PERMS,
+ "alternate descriptive text followed by one or more "
+ "filenames"),
+ AP_INIT_ITERATE2("AddAltByType", add_alt, BY_TYPE, DIR_CMD_PERMS,
+ "alternate descriptive text followed by one or more MIME "
+ "types"),
+ AP_INIT_ITERATE2("AddAltByEncoding", add_alt, BY_ENCODING, DIR_CMD_PERMS,
+ "alternate descriptive text followed by one or more "
+ "content encodings"),
+ AP_INIT_RAW_ARGS("IndexOptions", add_opts, NULL, DIR_CMD_PERMS,
+ "one or more index options [+|-][]"),
+ AP_INIT_TAKE2("IndexOrderDefault", set_default_order, NULL, DIR_CMD_PERMS,
+ "{Ascending,Descending} {Name,Size,Description,Date}"),
+ AP_INIT_ITERATE("IndexIgnore", add_ignore, NULL, DIR_CMD_PERMS,
+ "one or more file extensions"),
+ AP_INIT_ITERATE2("AddDescription", add_desc, BY_PATH, DIR_CMD_PERMS,
+ "Descriptive text followed by one or more filenames"),
+ AP_INIT_TAKE1("HeaderName", add_header, NULL, DIR_CMD_PERMS,
+ "a filename"),
+ AP_INIT_TAKE1("ReadmeName", add_readme, NULL, DIR_CMD_PERMS,
+ "a filename"),
+ AP_INIT_RAW_ARGS("FancyIndexing", ap_set_deprecated, NULL, OR_ALL,
+ "The FancyIndexing directive is no longer supported. "
+ "Use IndexOptions FancyIndexing."),
+ AP_INIT_TAKE1("DefaultIcon", ap_set_string_slot,
+ (void *)APR_OFFSETOF(autoindex_config_rec, default_icon),
+ DIR_CMD_PERMS, "an icon URL"),
+ {NULL}
+};
+
+static void *create_autoindex_config(apr_pool_t *p, char *dummy)
+{
+ autoindex_config_rec *new =
+ (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
+
+ new->icon_width = 0;
+ new->icon_height = 0;
+ new->name_width = DEFAULT_NAME_WIDTH;
+ new->name_adjust = K_UNSET;
+ new->desc_width = DEFAULT_DESC_WIDTH;
+ new->desc_adjust = K_UNSET;
+ new->icon_list = apr_array_make(p, 4, sizeof(struct item));
+ new->alt_list = apr_array_make(p, 4, sizeof(struct item));
+ new->desc_list = apr_array_make(p, 4, sizeof(ai_desc_t));
+ new->ign_list = apr_array_make(p, 4, sizeof(struct item));
+ new->hdr_list = apr_array_make(p, 4, sizeof(struct item));
+ new->rdme_list = apr_array_make(p, 4, sizeof(struct item));
+ new->opts = 0;
+ new->incremented_opts = 0;
+ new->decremented_opts = 0;
+ new->default_keyid = '\0';
+ new->default_direction = '\0';
+
+ return (void *) new;
+}
+
+static void *merge_autoindex_configs(apr_pool_t *p, void *basev, void *addv)
+{
+ autoindex_config_rec *new;
+ autoindex_config_rec *base = (autoindex_config_rec *) basev;
+ autoindex_config_rec *add = (autoindex_config_rec *) addv;
+
+ new = (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
+ new->default_icon = add->default_icon ? add->default_icon
+ : base->default_icon;
+ new->icon_height = add->icon_height ? add->icon_height : base->icon_height;
+ new->icon_width = add->icon_width ? add->icon_width : base->icon_width;
+
+ new->ctype = add->ctype ? add->ctype : base->ctype;
+ new->charset = add->charset ? add->charset : base->charset;
+
+ new->alt_list = apr_array_append(p, add->alt_list, base->alt_list);
+ new->ign_list = apr_array_append(p, add->ign_list, base->ign_list);
+ new->hdr_list = apr_array_append(p, add->hdr_list, base->hdr_list);
+ new->desc_list = apr_array_append(p, add->desc_list, base->desc_list);
+ new->icon_list = apr_array_append(p, add->icon_list, base->icon_list);
+ new->rdme_list = apr_array_append(p, add->rdme_list, base->rdme_list);
+ if (add->opts & NO_OPTIONS) {
+ /*
+ * If the current directory says 'no options' then we also
+ * clear any incremental mods from being inheritable further down.
+ */
+ new->opts = NO_OPTIONS;
+ new->incremented_opts = 0;
+ new->decremented_opts = 0;
+ }
+ else {
+ /*
+ * If there were any nonincremental options selected for
+ * this directory, they dominate and we don't inherit *anything.*
+ * Contrariwise, we *do* inherit if the only settings here are
+ * incremental ones.
+ */
+ if (add->opts == 0) {
+ new->incremented_opts = (base->incremented_opts
+ | add->incremented_opts)
+ & ~add->decremented_opts;
+ new->decremented_opts = (base->decremented_opts
+ | add->decremented_opts);
+ /*
+ * We may have incremental settings, so make sure we don't
+ * inadvertently inherit an IndexOptions None from above.
+ */
+ new->opts = (base->opts & ~NO_OPTIONS);
+ }
+ else {
+ /*
+ * There are local nonincremental settings, which clear
+ * all inheritance from above. They *are* the new base settings.
+ */
+ new->opts = add->opts;;
+ }
+ /*
+ * We're guaranteed that there'll be no overlap between
+ * the add-options and the remove-options.
+ */
+ new->opts |= new->incremented_opts;
+ new->opts &= ~new->decremented_opts;
+ }
+ /*
+ * Inherit the NameWidth settings if there aren't any specific to
+ * the new location; otherwise we'll end up using the defaults set in the
+ * config-rec creation routine.
+ */
+ if (add->name_adjust == K_UNSET) {
+ new->name_width = base->name_width;
+ new->name_adjust = base->name_adjust;
+ }
+ else {
+ new->name_width = add->name_width;
+ new->name_adjust = add->name_adjust;
+ }
+
+ /*
+ * Likewise for DescriptionWidth.
+ */
+ if (add->desc_adjust == K_UNSET) {
+ new->desc_width = base->desc_width;
+ new->desc_adjust = base->desc_adjust;
+ }
+ else {
+ new->desc_width = add->desc_width;
+ new->desc_adjust = add->desc_adjust;
+ }
+
+ new->default_keyid = add->default_keyid ? add->default_keyid
+ : base->default_keyid;
+ new->default_direction = add->default_direction ? add->default_direction
+ : base->default_direction;
+ return new;
+}
+
+/****************************************************************
+ *
+ * Looking things up in config entries...
+ */
+
+/* Structure used to hold entries when we're actually building an index */
+
+struct ent {
+ char *name;
+ char *icon;
+ char *alt;
+ char *desc;
+ apr_off_t size;
+ apr_time_t lm;
+ struct ent *next;
+ int ascending, ignore_case, version_sort;
+ char key;
+ int isdir;
+};
+
+static char *find_item(request_rec *r, apr_array_header_t *list, int path_only)
+{
+ const char *content_type = ap_field_noparam(r->pool, r->content_type);
+ const char *content_encoding = r->content_encoding;
+ char *path = r->filename;
+
+ struct item *items = (struct item *) list->elts;
+ int i;
+
+ for (i = 0; i < list->nelts; ++i) {
+ struct item *p = &items[i];
+
+ /* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */
+ if ((path[0] == '^') || (!ap_strcmp_match(path, p->apply_path))) {
+ if (!*(p->apply_to)) {
+ return p->data;
+ }
+ else if (p->type == BY_PATH || path[0] == '^') {
+ if (!ap_strcmp_match(path, p->apply_to)) {
+ return p->data;
+ }
+ }
+ else if (!path_only) {
+ if (!content_encoding) {
+ if (p->type == BY_TYPE) {
+ if (content_type
+ && !ap_strcasecmp_match(content_type,
+ p->apply_to)) {
+ return p->data;
+ }
+ }
+ }
+ else {
+ if (p->type == BY_ENCODING) {
+ if (!ap_strcasecmp_match(content_encoding,
+ p->apply_to)) {
+ return p->data;
+ }
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+#define find_icon(d,p,t) find_item(p,d->icon_list,t)
+#define find_alt(d,p,t) find_item(p,d->alt_list,t)
+#define find_header(d,p) find_item(p,d->hdr_list,0)
+#define find_readme(d,p) find_item(p,d->rdme_list,0)
+
+static char *find_default_item(char *bogus_name, apr_array_header_t *list)
+{
+ request_rec r;
+ /* Bleah. I tried to clean up find_item, and it lead to this bit
+ * of ugliness. Note that the fields initialized are precisely
+ * those that find_item looks at...
+ */
+ r.filename = bogus_name;
+ r.content_type = r.content_encoding = NULL;
+ return find_item(&r, list, 1);
+}
+
+#define find_default_icon(d,n) find_default_item(n, d->icon_list)
+#define find_default_alt(d,n) find_default_item(n, d->alt_list)
+
+/*
+ * Look through the list of pattern/description pairs and return the first one
+ * if any) that matches the filename in the request. If multiple patterns
+ * match, only the first one is used; since the order in the array is the
+ * same as the order in which directives were processed, earlier matching
+ * directives will dominate.
+ */
+
+#ifdef CASE_BLIND_FILESYSTEM
+#define MATCH_FLAGS FNM_CASE_BLIND
+#else
+#define MATCH_FLAGS 0
+#endif
+
+static char *find_desc(autoindex_config_rec *dcfg, const char *filename_full)
+{
+ int i;
+ ai_desc_t *list = (ai_desc_t *) dcfg->desc_list->elts;
+ const char *filename_only;
+ const char *filename;
+
+ /*
+ * If the filename includes a path, extract just the name itself
+ * for the simple matches.
+ */
+ if ((filename_only = ap_strrchr_c(filename_full, '/')) == NULL) {
+ filename_only = filename_full;
+ }
+ else {
+ filename_only++;
+ }
+ for (i = 0; i < dcfg->desc_list->nelts; ++i) {
+ ai_desc_t *tuple = &list[i];
+ int found;
+
+ /*
+ * Only use the full-path filename if the pattern contains '/'s.
+ */
+ filename = (tuple->full_path) ? filename_full : filename_only;
+ /*
+ * Make the comparison using the cheapest method; only do
+ * wildcard checking if we must.
+ */
+ if (tuple->wildcards) {
+ found = (apr_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0);
+ }
+ else {
+ found = (ap_strstr_c(filename, tuple->pattern) != NULL);
+ }
+ if (found) {
+ return tuple->description;
+ }
+ }
+ return NULL;
+}
+
+static int ignore_entry(autoindex_config_rec *d, char *path)
+{
+ apr_array_header_t *list = d->ign_list;
+ struct item *items = (struct item *) list->elts;
+ char *tt;
+ int i;
+
+ if ((tt = strrchr(path, '/')) == NULL) {
+ tt = path;
+ }
+ else {
+ tt++;
+ }
+
+ for (i = 0; i < list->nelts; ++i) {
+ struct item *p = &items[i];
+ char *ap;
+
+ if ((ap = strrchr(p->apply_to, '/')) == NULL) {
+ ap = p->apply_to;
+ }
+ else {
+ ap++;
+ }
+
+#ifndef CASE_BLIND_FILESYSTEM
+ if (!ap_strcmp_match(path, p->apply_path)
+ && !ap_strcmp_match(tt, ap)) {
+ return 1;
+ }
+#else /* !CASE_BLIND_FILESYSTEM */
+ /*
+ * On some platforms, the match must be case-blind. This is really
+ * a factor of the filesystem involved, but we can't detect that
+ * reliably - so we have to granularise at the OS level.
+ */
+ if (!ap_strcasecmp_match(path, p->apply_path)
+ && !ap_strcasecmp_match(tt, ap)) {
+ return 1;
+ }
+#endif /* !CASE_BLIND_FILESYSTEM */
+ }
+ return 0;
+}
+
+/*****************************************************************
+ *
+ * Actually generating output
+ */
+
+/*
+ * Elements of the emitted document:
+ * Preamble
+ * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
+ * succeeds for the (content_type == text/html) header file.
+ * Header file
+ * Emitted if found (and able).
+ * H1 tag line
+ * Emitted if a header file is NOT emitted.
+ * Directory stuff
+ * Always emitted.
+ * HR
+ * Emitted if FANCY_INDEXING is set.
+ * Readme file
+ * Emitted if found (and able).
+ * ServerSig
+ * Emitted if ServerSignature is not Off AND a readme file
+ * is NOT emitted.
+ * Postamble
+ * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
+ * succeeds for the (content_type == text/html) readme file.
+ */
+
+
+/*
+ * emit a plain text file
+ */
+static void do_emit_plain(request_rec *r, apr_file_t *f)
+{
+ char buf[AP_IOBUFSIZE + 1];
+ int ch;
+ apr_size_t i, c, n;
+ apr_status_t rv;
+
+ ap_rputs("<pre>\n", r);
+ while (!apr_file_eof(f)) {
+ do {
+ n = sizeof(char) * AP_IOBUFSIZE;
+ rv = apr_file_read(f, buf, &n);
+ } while (APR_STATUS_IS_EINTR(rv));
+ if (n == 0 || rv != APR_SUCCESS) {
+ /* ###: better error here? */
+ break;
+ }
+ buf[n] = '\0';
+ c = 0;
+ while (c < n) {
+ for (i = c; i < n; i++) {
+ if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') {
+ break;
+ }
+ }
+ ch = buf[i];
+ buf[i] = '\0';
+ ap_rputs(&buf[c], r);
+ if (ch == '<') {
+ ap_rputs("&lt;", r);
+ }
+ else if (ch == '>') {
+ ap_rputs("&gt;", r);
+ }
+ else if (ch == '&') {
+ ap_rputs("&amp;", r);
+ }
+ c = i + 1;
+ }
+ }
+ ap_rputs("</pre>\n", r);
+}
+
+/*
+ * Handle the preamble through the H1 tag line, inclusive. Locate
+ * the file with a subrequests. Process text/html documents by actually
+ * running the subrequest; text/xxx documents get copied verbatim,
+ * and any other content type is ignored. This means that a non-text
+ * document (such as HEADER.gif) might get multiviewed as the result
+ * instead of a text document, meaning nothing will be displayed, but
+ * oh well.
+ */
+static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
+ int emit_xhtml, char *title)
+{
+ apr_table_t *hdrs = r->headers_in;
+ apr_file_t *f = NULL;
+ request_rec *rr = NULL;
+ int emit_amble = 1;
+ int emit_H1 = 1;
+ const char *r_accept;
+ const char *r_accept_enc;
+
+ /*
+ * If there's a header file, send a subrequest to look for it. If it's
+ * found and html do the subrequest, otherwise handle it
+ */
+ r_accept = apr_table_get(hdrs, "Accept");
+ r_accept_enc = apr_table_get(hdrs, "Accept-Encoding");
+ apr_table_setn(hdrs, "Accept", "text/html, text/plain");
+ apr_table_unset(hdrs, "Accept-Encoding");
+
+
+ if ((header_fname != NULL) && r->args) {
+ header_fname = apr_pstrcat(r->pool, header_fname, "?", r->args, NULL);
+ }
+
+ if ((header_fname != NULL)
+ && (rr = ap_sub_req_lookup_uri(header_fname, r, r->output_filters))
+ && (rr->status == HTTP_OK)
+ && (rr->filename != NULL)
+ && (rr->finfo.filetype == APR_REG)) {
+ /*
+ * Check for the two specific cases we allow: text/html and
+ * text/anything-else. The former is allowed to be processed for
+ * SSIs.
+ */
+ if (rr->content_type != NULL) {
+ if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
+ "text/html")) {
+ ap_filter_t *f;
+ /* Hope everything will work... */
+ emit_amble = 0;
+ emit_H1 = 0;
+
+ if (! suppress_amble) {
+ emit_preamble(r, emit_xhtml, title);
+ }
+ /* This is a hack, but I can't find any better way to do this.
+ * The problem is that we have already created the sub-request,
+ * but we just inserted the OLD_WRITE filter, and the
+ * sub-request needs to pass its data through the OLD_WRITE
+ * filter, or things go horribly wrong (missing data, data in
+ * the wrong order, etc). To fix it, if you create a
+ * sub-request and then insert the OLD_WRITE filter before you
+ * run the request, you need to make sure that the sub-request
+ * data goes through the OLD_WRITE filter. Just steal this
+ * code. The long-term solution is to remove the ap_r*
+ * functions.
+ */
+ for (f=rr->output_filters;
+ f->frec != ap_subreq_core_filter_handle; f = f->next);
+ f->next = r->output_filters;
+
+ /*
+ * If there's a problem running the subrequest, display the
+ * preamble if we didn't do it before -- the header file
+ * didn't get displayed.
+ */
+ if (ap_run_sub_req(rr) != OK) {
+ /* It didn't work */
+ emit_amble = suppress_amble;
+ emit_H1 = 1;
+ }
+ }
+ else if (!strncasecmp("text/", rr->content_type, 5)) {
+ /*
+ * If we can open the file, prefix it with the preamble
+ * regardless; since we'll be sending a <pre> block around
+ * the file's contents, any HTML header it had won't end up
+ * where it belongs.
+ */
+ if (apr_file_open(&f, rr->filename, APR_READ,
+ APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
+ emit_preamble(r, emit_xhtml, title);
+ emit_amble = 0;
+ do_emit_plain(r, f);
+ apr_file_close(f);
+ emit_H1 = 0;
+ }
+ }
+ }
+ }
+
+ if (r_accept) {
+ apr_table_setn(hdrs, "Accept", r_accept);
+ }
+ else {
+ apr_table_unset(hdrs, "Accept");
+ }
+
+ if (r_accept_enc) {
+ apr_table_setn(hdrs, "Accept-Encoding", r_accept_enc);
+ }
+
+ if (emit_amble) {
+ emit_preamble(r, emit_xhtml, title);
+ }
+ if (emit_H1) {
+ ap_rvputs(r, "<h1>Index of ", title, "</h1>\n", NULL);
+ }
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
+ }
+}
+
+
+/*
+ * Handle the Readme file through the postamble, inclusive. Locate
+ * the file with a subrequests. Process text/html documents by actually
+ * running the subrequest; text/xxx documents get copied verbatim,
+ * and any other content type is ignored. This means that a non-text
+ * document (such as FOOTER.gif) might get multiviewed as the result
+ * instead of a text document, meaning nothing will be displayed, but
+ * oh well.
+ */
+static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
+{
+ apr_file_t *f = NULL;
+ request_rec *rr = NULL;
+ int suppress_post = 0;
+ int suppress_sig = 0;
+
+ /*
+ * If there's a readme file, send a subrequest to look for it. If it's
+ * found and a text file, handle it -- otherwise fall through and
+ * pretend there's nothing there.
+ */
+ if ((readme_fname != NULL)
+ && (rr = ap_sub_req_lookup_uri(readme_fname, r, r->output_filters))
+ && (rr->status == HTTP_OK)
+ && (rr->filename != NULL)
+ && rr->finfo.filetype == APR_REG) {
+ /*
+ * Check for the two specific cases we allow: text/html and
+ * text/anything-else. The former is allowed to be processed for
+ * SSIs.
+ */
+ if (rr->content_type != NULL) {
+ if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
+ "text/html")) {
+ ap_filter_t *f;
+ for (f=rr->output_filters;
+ f->frec != ap_subreq_core_filter_handle; f = f->next);
+ f->next = r->output_filters;
+
+
+ if (ap_run_sub_req(rr) == OK) {
+ /* worked... */
+ suppress_sig = 1;
+ suppress_post = suppress_amble;
+ }
+ }
+ else if (!strncasecmp("text/", rr->content_type, 5)) {
+ /*
+ * If we can open the file, suppress the signature.
+ */
+ if (apr_file_open(&f, rr->filename, APR_READ,
+ APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
+ do_emit_plain(r, f);
+ apr_file_close(f);
+ suppress_sig = 1;
+ }
+ }
+ }
+ }
+
+ if (!suppress_sig) {
+ ap_rputs(ap_psignature("", r), r);
+ }
+ if (!suppress_post) {
+ ap_rputs("</body></html>\n", r);
+ }
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
+ }
+}
+
+
+static char *find_title(request_rec *r)
+{
+ char titlebuf[MAX_STRING_LEN], *find = "<title>";
+ apr_file_t *thefile = NULL;
+ int x, y, p;
+ apr_size_t n;
+
+ if (r->status != HTTP_OK) {
+ return NULL;
+ }
+ if ((r->content_type != NULL)
+ && (!strcasecmp(ap_field_noparam(r->pool, r->content_type),
+ "text/html")
+ || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE))
+ && !r->content_encoding) {
+ if (apr_file_open(&thefile, r->filename, APR_READ,
+ APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
+ return NULL;
+ }
+ n = sizeof(char) * (MAX_STRING_LEN - 1);
+ apr_file_read(thefile, titlebuf, &n);
+ if (n <= 0) {
+ apr_file_close(thefile);
+ return NULL;
+ }
+ titlebuf[n] = '\0';
+ for (x = 0, p = 0; titlebuf[x]; x++) {
+ if (apr_tolower(titlebuf[x]) == find[p]) {
+ if (!find[++p]) {
+ if ((p = ap_ind(&titlebuf[++x], '<')) != -1) {
+ titlebuf[x + p] = '\0';
+ }
+ /* Scan for line breaks for Tanmoy's secretary */
+ for (y = x; titlebuf[y]; y++) {
+ if ((titlebuf[y] == CR) || (titlebuf[y] == LF)) {
+ if (y == x) {
+ x++;
+ }
+ else {
+ titlebuf[y] = ' ';
+ }
+ }
+ }
+ apr_file_close(thefile);
+ return apr_pstrdup(r->pool, &titlebuf[x]);
+ }
+ }
+ else {
+ p = 0;
+ }
+ }
+ apr_file_close(thefile);
+ }
+ return NULL;
+}
+
+static struct ent *make_parent_entry(apr_int32_t autoindex_opts,
+ autoindex_config_rec *d,
+ request_rec *r, char keyid,
+ char direction)
+{
+ struct ent *p = (struct ent *) apr_pcalloc(r->pool, sizeof(struct ent));
+ char *testpath;
+ /*
+ * p->name is now the true parent URI.
+ * testpath is a crafted lie, so that the syntax '/some/..'
+ * (or simply '..')be used to describe 'up' from '/some/'
+ * when processeing IndexIgnore, and Icon|Alt|Desc configs.
+ */
+
+ /* The output has always been to the parent. Don't make ourself
+ * our own parent (worthless cyclical reference).
+ */
+ if (!(p->name = ap_make_full_path(r->pool, r->uri, "../"))) {
+ return (NULL);
+ }
+ ap_getparents(p->name);
+ if (!*p->name) {
+ return (NULL);
+ }
+
+ /* IndexIgnore has always compared "/thispath/.." */
+ testpath = ap_make_full_path(r->pool, r->filename, "..");
+ if (ignore_entry(d, testpath)) {
+ return (NULL);
+ }
+
+ p->size = -1;
+ p->lm = -1;
+ p->key = apr_toupper(keyid);
+ p->ascending = (apr_toupper(direction) == D_ASCENDING);
+ p->version_sort = autoindex_opts & VERSION_SORT;
+ if (autoindex_opts & FANCY_INDEXING) {
+ if (!(p->icon = find_default_icon(d, testpath))) {
+ p->icon = find_default_icon(d, "^^DIRECTORY^^");
+ }
+ if (!(p->alt = find_default_alt(d, testpath))) {
+ if (!(p->alt = find_default_alt(d, "^^DIRECTORY^^"))) {
+ p->alt = "DIR";
+ }
+ }
+ p->desc = find_desc(d, testpath);
+ }
+ return p;
+}
+
+static struct ent *make_autoindex_entry(const apr_finfo_t *dirent,
+ int autoindex_opts,
+ autoindex_config_rec *d,
+ request_rec *r, char keyid,
+ char direction,
+ const char *pattern)
+{
+ request_rec *rr;
+ struct ent *p;
+
+ /* Dot is ignored, Parent is handled by make_parent_entry() */
+ if ((dirent->name[0] == '.') && (!dirent->name[1]
+ || ((dirent->name[1] == '.') && !dirent->name[2])))
+ return (NULL);
+
+#ifndef CASE_BLIND_FILESYSTEM
+ if (pattern && (apr_fnmatch(pattern, dirent->name,
+ FNM_NOESCAPE | FNM_PERIOD)
+ != APR_SUCCESS))
+ return (NULL);
+#else /* !CASE_BLIND_FILESYSTEM */
+ /*
+ * On some platforms, the match must be case-blind. This is really
+ * a factor of the filesystem involved, but we can't detect that
+ * reliably - so we have to granularise at the OS level.
+ */
+ if (pattern && (apr_fnmatch(pattern, dirent->name,
+ FNM_NOESCAPE | FNM_PERIOD | FNM_CASE_BLIND)
+ != APR_SUCCESS))
+ return (NULL);
+#endif /* !CASE_BLIND_FILESYSTEM */
+
+ if (ignore_entry(d, ap_make_full_path(r->pool,
+ r->filename, dirent->name))) {
+ return (NULL);
+ }
+
+ if (!(rr = ap_sub_req_lookup_dirent(dirent, r, AP_SUBREQ_NO_ARGS, NULL))) {
+ return (NULL);
+ }
+
+ if ((rr->finfo.filetype != APR_DIR && rr->finfo.filetype != APR_REG)
+ || !(rr->status == OK || ap_is_HTTP_SUCCESS(rr->status)
+ || ap_is_HTTP_REDIRECT(rr->status))) {
+ ap_destroy_sub_req(rr);
+ return (NULL);
+ }
+
+ p = (struct ent *) apr_pcalloc(r->pool, sizeof(struct ent));
+ if (dirent->filetype == APR_DIR) {
+ p->name = apr_pstrcat(r->pool, dirent->name, "/", NULL);
+ }
+ else {
+ p->name = apr_pstrdup(r->pool, dirent->name);
+ }
+ p->size = -1;
+ p->icon = NULL;
+ p->alt = NULL;
+ p->desc = NULL;
+ p->lm = -1;
+ p->isdir = 0;
+ p->key = apr_toupper(keyid);
+ p->ascending = (apr_toupper(direction) == D_ASCENDING);
+ p->version_sort = !!(autoindex_opts & VERSION_SORT);
+ p->ignore_case = !!(autoindex_opts & IGNORE_CASE);
+
+ if (autoindex_opts & (FANCY_INDEXING | TABLE_INDEXING)) {
+ p->lm = rr->finfo.mtime;
+ if (dirent->filetype == APR_DIR) {
+ if (autoindex_opts & FOLDERS_FIRST) {
+ p->isdir = 1;
+ }
+ rr->filename = ap_make_dirstr_parent (rr->pool, rr->filename);
+
+ /* omit the trailing slash (1.3 compat) */
+ rr->filename[strlen(rr->filename) - 1] = '\0';
+
+ if (!(p->icon = find_icon(d, rr, 1))) {
+ p->icon = find_default_icon(d, "^^DIRECTORY^^");
+ }
+ if (!(p->alt = find_alt(d, rr, 1))) {
+ if (!(p->alt = find_default_alt(d, "^^DIRECTORY^^"))) {
+ p->alt = "DIR";
+ }
+ }
+ }
+ else {
+ p->icon = find_icon(d, rr, 0);
+ p->alt = find_alt(d, rr, 0);
+ p->size = rr->finfo.size;
+ }
+
+ p->desc = find_desc(d, rr->filename);
+
+ if ((!p->desc) && (autoindex_opts & SCAN_HTML_TITLES)) {
+ p->desc = apr_pstrdup(r->pool, find_title(rr));
+ }
+ }
+ ap_destroy_sub_req(rr);
+ /*
+ * We don't need to take any special action for the file size key.
+ * If we did, it would go here.
+ */
+ if (keyid == K_LAST_MOD) {
+ if (p->lm < 0) {
+ p->lm = 0;
+ }
+ }
+ return (p);
+}
+
+static char *terminate_description(autoindex_config_rec *d, char *desc,
+ apr_int32_t autoindex_opts, int desc_width)
+{
+ int maxsize = desc_width;
+ register int x;
+
+ /*
+ * If there's no DescriptionWidth in effect, default to the old
+ * behaviour of adjusting the description size depending upon
+ * what else is being displayed. Otherwise, stick with the
+ * setting.
+ */
+ if (d->desc_adjust == K_UNSET) {
+ if (autoindex_opts & SUPPRESS_ICON) {
+ maxsize += 6;
+ }
+ if (autoindex_opts & SUPPRESS_LAST_MOD) {
+ maxsize += 19;
+ }
+ if (autoindex_opts & SUPPRESS_SIZE) {
+ maxsize += 7;
+ }
+ }
+ for (x = 0; desc[x] && ((maxsize > 0) || (desc[x] == '<')); x++) {
+ if (desc[x] == '<') {
+ while (desc[x] != '>') {
+ if (!desc[x]) {
+ maxsize = 0;
+ break;
+ }
+ ++x;
+ }
+ }
+ else if (desc[x] == '&') {
+ /* entities like &auml; count as one character */
+ --maxsize;
+ for ( ; desc[x] != ';'; ++x) {
+ if (desc[x] == '\0') {
+ maxsize = 0;
+ break;
+ }
+ }
+ }
+ else {
+ --maxsize;
+ }
+ }
+ if (!maxsize && desc[x] != '\0') {
+ desc[x - 1] = '>'; /* Grump. */
+ desc[x] = '\0'; /* Double Grump! */
+ }
+ return desc;
+}
+
+/*
+ * Emit the anchor for the specified field. If a field is the key for the
+ * current request, the link changes its meaning to reverse the order when
+ * selected again. Non-active fields always start in ascending order.
+ */
+static void emit_link(request_rec *r, const char *anchor, char column,
+ char curkey, char curdirection,
+ const char *colargs, int nosort)
+{
+ if (!nosort) {
+ char qvalue[9];
+
+ qvalue[0] = '?';
+ qvalue[1] = 'C';
+ qvalue[2] = '=';
+ qvalue[3] = column;
+ qvalue[4] = ';';
+ qvalue[5] = 'O';
+ qvalue[6] = '=';
+ /* reverse? */
+ qvalue[7] = ((curkey == column) && (curdirection == D_ASCENDING))
+ ? D_DESCENDING : D_ASCENDING;
+ qvalue[8] = '\0';
+ ap_rvputs(r, "<a href=\"", qvalue, colargs ? colargs : "",
+ "\">", anchor, "</a>", NULL);
+ }
+ else {
+ ap_rputs(anchor, r);
+ }
+}
+
+static void output_directories(struct ent **ar, int n,
+ autoindex_config_rec *d, request_rec *r,
+ apr_int32_t autoindex_opts, char keyid,
+ char direction, const char *colargs)
+{
+ int x;
+ apr_size_t rv;
+ char *name = r->uri;
+ char *tp;
+ int static_columns = !!(autoindex_opts & SUPPRESS_COLSORT);
+ apr_pool_t *scratch;
+ int name_width;
+ int desc_width;
+ char *name_scratch;
+ char *pad_scratch;
+ char *breakrow = "";
+
+ apr_pool_create(&scratch, r->pool);
+ if (name[0] == '\0') {
+ name = "/";
+ }
+
+ name_width = d->name_width;
+ desc_width = d->desc_width;
+
+ if ((autoindex_opts & (FANCY_INDEXING | TABLE_INDEXING))
+ == FANCY_INDEXING) {
+ if (d->name_adjust == K_ADJUST) {
+ for (x = 0; x < n; x++) {
+ int t = strlen(ar[x]->name);
+ if (t > name_width) {
+ name_width = t;
+ }
+ }
+ }
+
+ if (d->desc_adjust == K_ADJUST) {
+ for (x = 0; x < n; x++) {
+ if (ar[x]->desc != NULL) {
+ int t = strlen(ar[x]->desc);
+ if (t > desc_width) {
+ desc_width = t;
+ }
+ }
+ }
+ }
+ }
+ name_scratch = apr_palloc(r->pool, name_width + 1);
+ pad_scratch = apr_palloc(r->pool, name_width + 1);
+ memset(pad_scratch, ' ', name_width);
+ pad_scratch[name_width] = '\0';
+
+ if (autoindex_opts & TABLE_INDEXING) {
+ int cols = 1;
+ ap_rputs("<table><tr>", r);
+ if (!(autoindex_opts & SUPPRESS_ICON)) {
+ ap_rputs("<th>", r);
+ if ((tp = find_default_icon(d, "^^BLANKICON^^"))) {
+ ap_rvputs(r, "<img src=\"", ap_escape_html(scratch, tp),
+ "\" alt=\"[ICO]\"", NULL);
+ if (d->icon_width) {
+ ap_rprintf(r, " width=\"%d\"", d->icon_width);
+ }
+ if (d->icon_height) {
+ ap_rprintf(r, " height=\"%d\"", d->icon_height);
+ }
+
+ if (autoindex_opts & EMIT_XHTML) {
+ ap_rputs(" /", r);
+ }
+ ap_rputs("></th>", r);
+ }
+ else {
+ ap_rputs("&nbsp;</th>", r);
+ }
+
+ ++cols;
+ }
+ ap_rputs("<th>", r);
+ emit_link(r, "Name", K_NAME, keyid, direction,
+ colargs, static_columns);
+ if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
+ ap_rputs("</th><th>", r);
+ emit_link(r, "Last modified", K_LAST_MOD, keyid, direction,
+ colargs, static_columns);
+ ++cols;
+ }
+ if (!(autoindex_opts & SUPPRESS_SIZE)) {
+ ap_rputs("</th><th>", r);
+ emit_link(r, "Size", K_SIZE, keyid, direction,
+ colargs, static_columns);
+ ++cols;
+ }
+ if (!(autoindex_opts & SUPPRESS_DESC)) {
+ ap_rputs("</th><th>", r);
+ emit_link(r, "Description", K_DESC, keyid, direction,
+ colargs, static_columns);
+ ++cols;
+ }
+ if (!(autoindex_opts & SUPPRESS_RULES)) {
+ breakrow = apr_psprintf(r->pool,
+ "<tr><th colspan=\"%d\">"
+ "<hr%s></th></tr>\n", cols,
+ (autoindex_opts & EMIT_XHTML) ? " /" : "");
+ }
+ ap_rvputs(r, "</th></tr>", breakrow, NULL);
+ }
+ else if (autoindex_opts & FANCY_INDEXING) {
+ ap_rputs("<pre>", r);
+ if (!(autoindex_opts & SUPPRESS_ICON)) {
+ if ((tp = find_default_icon(d, "^^BLANKICON^^"))) {
+ ap_rvputs(r, "<img src=\"", ap_escape_html(scratch, tp),
+ "\" alt=\"Icon \"", NULL);
+ if (d->icon_width) {
+ ap_rprintf(r, " width=\"%d\"", d->icon_width);
+ }
+ if (d->icon_height) {
+ ap_rprintf(r, " height=\"%d\"", d->icon_height);
+ }
+
+ if (autoindex_opts & EMIT_XHTML) {
+ ap_rputs(" /", r);
+ }
+ ap_rputs("> ", r);
+ }
+ else {
+ ap_rputs(" ", r);
+ }
+ }
+ emit_link(r, "Name", K_NAME, keyid, direction,
+ colargs, static_columns);
+ ap_rputs(pad_scratch + 4, r);
+ /*
+ * Emit the guaranteed-at-least-one-space-between-columns byte.
+ */
+ ap_rputs(" ", r);
+ if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
+ emit_link(r, "Last modified", K_LAST_MOD, keyid, direction,
+ colargs, static_columns);
+ ap_rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_SIZE)) {
+ emit_link(r, "Size", K_SIZE, keyid, direction,
+ colargs, static_columns);
+ ap_rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_DESC)) {
+ emit_link(r, "Description", K_DESC, keyid, direction,
+ colargs, static_columns);
+ }
+ if (!(autoindex_opts & SUPPRESS_RULES)) {
+ ap_rputs("<hr", r);
+ if (autoindex_opts & EMIT_XHTML) {
+ ap_rputs(" /", r);
+ }
+ ap_rputs(">", r);
+ }
+ else {
+ ap_rputc('\n', r);
+ }
+ }
+ else {
+ ap_rputs("<ul>", r);
+ }
+
+ for (x = 0; x < n; x++) {
+ char *anchor, *t, *t2;
+ int nwidth;
+
+ apr_pool_clear(scratch);
+
+ t = ar[x]->name;
+ anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
+
+ if (!x && t[0] == '/') {
+ t2 = "Parent Directory";
+ }
+ else {
+ t2 = t;
+ }
+
+ if (autoindex_opts & TABLE_INDEXING) {
+ ap_rputs("<tr>", r);
+ if (!(autoindex_opts & SUPPRESS_ICON)) {
+ ap_rputs("<td valign=\"top\">", r);
+ if (autoindex_opts & ICONS_ARE_LINKS) {
+ ap_rvputs(r, "<a href=\"", anchor, "\">", NULL);
+ }
+ if ((ar[x]->icon) || d->default_icon) {
+ ap_rvputs(r, "<img src=\"",
+ ap_escape_html(scratch,
+ ar[x]->icon ? ar[x]->icon
+ : d->default_icon),
+ "\" alt=\"[", (ar[x]->alt ? ar[x]->alt : " "),
+ "]\"", NULL);
+ if (d->icon_width) {
+ ap_rprintf(r, " width=\"%d\"", d->icon_width);
+ }
+ if (d->icon_height) {
+ ap_rprintf(r, " height=\"%d\"", d->icon_height);
+ }
+
+ if (autoindex_opts & EMIT_XHTML) {
+ ap_rputs(" /", r);
+ }
+ ap_rputs(">", r);
+ }
+ else {
+ ap_rputs("&nbsp;", r);
+ }
+ if (autoindex_opts & ICONS_ARE_LINKS) {
+ ap_rputs("</a></td>", r);
+ }
+ else {
+ ap_rputs("</td>", r);
+ }
+ }
+ if (d->name_adjust == K_ADJUST) {
+ ap_rvputs(r, "<td><a href=\"", anchor, "\">",
+ ap_escape_html(scratch, t2), "</a>", NULL);
+ }
+ else {
+ nwidth = strlen(t2);
+ if (nwidth > name_width) {
+ memcpy(name_scratch, t2, name_width - 3);
+ name_scratch[name_width - 3] = '.';
+ name_scratch[name_width - 2] = '.';
+ name_scratch[name_width - 1] = '>';
+ name_scratch[name_width] = 0;
+ t2 = name_scratch;
+ nwidth = name_width;
+ }
+ ap_rvputs(r, "<td><a href=\"", anchor, "\">",
+ ap_escape_html(scratch, t2),
+ "</a>", pad_scratch + nwidth, NULL);
+ }
+ if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
+ if (ar[x]->lm != -1) {
+ char time_str[MAX_STRING_LEN];
+ apr_time_exp_t ts;
+ apr_time_exp_lt(&ts, ar[x]->lm);
+ apr_strftime(time_str, &rv, MAX_STRING_LEN,
+ "</td><td align=\"right\">%d-%b-%Y %H:%M ",
+ &ts);
+ ap_rputs(time_str, r);
+ }
+ else {
+ ap_rputs("</td><td>&nbsp;", r);
+ }
+ }
+ if (!(autoindex_opts & SUPPRESS_SIZE)) {
+ char buf[5];
+ ap_rvputs(r, "</td><td align=\"right\">",
+ apr_strfsize(ar[x]->size, buf), NULL);
+ }
+ if (!(autoindex_opts & SUPPRESS_DESC)) {
+ if (ar[x]->desc) {
+ if (d->desc_adjust == K_ADJUST) {
+ ap_rvputs(r, "</td><td>", ar[x]->desc, NULL);
+ }
+ else {
+ ap_rvputs(r, "</td><td>",
+ terminate_description(d, ar[x]->desc,
+ autoindex_opts,
+ desc_width), NULL);
+ }
+ }
+ }
+ else {
+ ap_rputs("</td><td>&nbsp;", r);
+ }
+ ap_rputs("</td></tr>\n", r);
+ }
+ else if (autoindex_opts & FANCY_INDEXING) {
+ if (!(autoindex_opts & SUPPRESS_ICON)) {
+ if (autoindex_opts & ICONS_ARE_LINKS) {
+ ap_rvputs(r, "<a href=\"", anchor, "\">", NULL);
+ }
+ if ((ar[x]->icon) || d->default_icon) {
+ ap_rvputs(r, "<img src=\"",
+ ap_escape_html(scratch,
+ ar[x]->icon ? ar[x]->icon
+ : d->default_icon),
+ "\" alt=\"[", (ar[x]->alt ? ar[x]->alt : " "),
+ "]\"", NULL);
+ if (d->icon_width) {
+ ap_rprintf(r, " width=\"%d\"", d->icon_width);
+ }
+ if (d->icon_height) {
+ ap_rprintf(r, " height=\"%d\"", d->icon_height);
+ }
+
+ if (autoindex_opts & EMIT_XHTML) {
+ ap_rputs(" /", r);
+ }
+ ap_rputs(">", r);
+ }
+ else {
+ ap_rputs(" ", r);
+ }
+ if (autoindex_opts & ICONS_ARE_LINKS) {
+ ap_rputs("</a> ", r);
+ }
+ else {
+ ap_rputc(' ', r);
+ }
+ }
+ nwidth = strlen(t2);
+ if (nwidth > name_width) {
+ memcpy(name_scratch, t2, name_width - 3);
+ name_scratch[name_width - 3] = '.';
+ name_scratch[name_width - 2] = '.';
+ name_scratch[name_width - 1] = '>';
+ name_scratch[name_width] = 0;
+ t2 = name_scratch;
+ nwidth = name_width;
+ }
+ ap_rvputs(r, "<a href=\"", anchor, "\">",
+ ap_escape_html(scratch, t2),
+ "</a>", pad_scratch + nwidth, NULL);
+ /*
+ * The blank before the storm.. er, before the next field.
+ */
+ ap_rputs(" ", r);
+ if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
+ if (ar[x]->lm != -1) {
+ char time_str[MAX_STRING_LEN];
+ apr_time_exp_t ts;
+ apr_time_exp_lt(&ts, ar[x]->lm);
+ apr_strftime(time_str, &rv, MAX_STRING_LEN,
+ "%d-%b-%Y %H:%M ", &ts);
+ ap_rputs(time_str, r);
+ }
+ else {
+ /*Length="22-Feb-1998 23:42 " (see 4 lines above) */
+ ap_rputs(" ", r);
+ }
+ }
+ if (!(autoindex_opts & SUPPRESS_SIZE)) {
+ char buf[5];
+ ap_rputs(apr_strfsize(ar[x]->size, buf), r);
+ ap_rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_DESC)) {
+ if (ar[x]->desc) {
+ ap_rputs(terminate_description(d, ar[x]->desc,
+ autoindex_opts,
+ desc_width), r);
+ }
+ }
+ ap_rputc('\n', r);
+ }
+ else {
+ ap_rvputs(r, "<li><a href=\"", anchor, "\"> ", t2,
+ "</a></li>\n", NULL);
+ }
+ }
+ if (autoindex_opts & TABLE_INDEXING) {
+ ap_rvputs(r, breakrow, "</table>\n", NULL);
+ }
+ else if (autoindex_opts & FANCY_INDEXING) {
+ if (!(autoindex_opts & SUPPRESS_RULES)) {
+ ap_rputs("<hr", r);
+ if (autoindex_opts & EMIT_XHTML) {
+ ap_rputs(" /", r);
+ }
+ ap_rputs("></pre>\n", r);
+ }
+ else {
+ ap_rputs("</pre>\n", r);
+ }
+ }
+ else {
+ ap_rputs("</ul>\n", r);
+ }
+}
+
+/*
+ * Compare two file entries according to the sort criteria. The return
+ * is essentially a signum function value.
+ */
+
+static int dsortf(struct ent **e1, struct ent **e2)
+{
+ struct ent *c1;
+ struct ent *c2;
+ int result = 0;
+
+ /*
+ * First, see if either of the entries is for the parent directory.
+ * If so, that *always* sorts lower than anything else.
+ */
+ if ((*e1)->name[0] == '/') {
+ return -1;
+ }
+ if ((*e2)->name[0] == '/') {
+ return 1;
+ }
+ /*
+ * Now see if one's a directory and one isn't, if we're set
+ * isdir for FOLDERS_FIRST.
+ */
+ if ((*e1)->isdir != (*e2)->isdir) {
+ return (*e1)->isdir ? -1 : 1;
+ }
+ /*
+ * All of our comparisons will be of the c1 entry against the c2 one,
+ * so assign them appropriately to take care of the ordering.
+ */
+ if ((*e1)->ascending) {
+ c1 = *e1;
+ c2 = *e2;
+ }
+ else {
+ c1 = *e2;
+ c2 = *e1;
+ }
+
+ switch (c1->key) {
+ case K_LAST_MOD:
+ if (c1->lm > c2->lm) {
+ return 1;
+ }
+ else if (c1->lm < c2->lm) {
+ return -1;
+ }
+ break;
+ case K_SIZE:
+ if (c1->size > c2->size) {
+ return 1;
+ }
+ else if (c1->size < c2->size) {
+ return -1;
+ }
+ break;
+ case K_DESC:
+ if (c1->version_sort) {
+ result = apr_strnatcmp(c1->desc ? c1->desc : "",
+ c2->desc ? c2->desc : "");
+ }
+ else {
+ result = strcmp(c1->desc ? c1->desc : "",
+ c2->desc ? c2->desc : "");
+ }
+ if (result) {
+ return result;
+ }
+ break;
+ }
+
+ /* names may identical when treated case-insensitively,
+ * so always fall back on strcmp() flavors to put entries
+ * in deterministic order. This means that 'ABC' and 'abc'
+ * will always appear in the same order, rather than
+ * variably between 'ABC abc' and 'abc ABC' order.
+ */
+
+ if (c1->version_sort) {
+ if (c1->ignore_case) {
+ result = apr_strnatcasecmp (c1->name, c2->name);
+ }
+ if (!result) {
+ result = apr_strnatcmp(c1->name, c2->name);
+ }
+ }
+
+ /* The names may be identical in respects other other than
+ * filename case when strnatcmp is used above, so fall back
+ * to strcmp on conflicts so that fn1.01.zzz and fn1.1.zzz
+ * are also sorted in a deterministic order.
+ */
+
+ if (!result && c1->ignore_case) {
+ result = strcasecmp (c1->name, c2->name);
+ }
+ if (!result) {
+ result = strcmp (c1->name, c2->name);
+ }
+ return result;
+}
+
+
+static int index_directory(request_rec *r,
+ autoindex_config_rec *autoindex_conf)
+{
+ char *title_name = ap_escape_html(r->pool, r->uri);
+ char *title_endp;
+ char *name = r->filename;
+ char *pstring = NULL;
+ apr_finfo_t dirent;
+ apr_dir_t *thedir;
+ apr_status_t status;
+ int num_ent = 0, x;
+ struct ent *head, *p;
+ struct ent **ar = NULL;
+ const char *qstring;
+ apr_int32_t autoindex_opts = autoindex_conf->opts;
+ char keyid;
+ char direction;
+ char *colargs;
+ char *fullpath;
+ apr_size_t dirpathlen;
+ char *ctype = "text/html";
+ char *charset;
+
+ if ((status = apr_dir_open(&thedir, name, r->pool)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+ "Can't open directory for index: %s", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+
+ if (autoindex_conf->ctype) {
+ ctype = autoindex_conf->ctype;
+ }
+ if (autoindex_conf->charset) {
+ charset = autoindex_conf->charset;
+ }
+ else {
+#if APR_HAS_UNICODE_FS
+ charset = "UTF-8";
+#else
+ charset = "ISO-8859-1";
+#endif
+ }
+ if (*charset) {
+ ap_set_content_type(r, apr_pstrcat(r->pool, ctype, ";charset=",
+ charset, NULL));
+ }
+ else {
+ ap_set_content_type(r, ctype);
+ }
+
+ if (autoindex_opts & TRACK_MODIFIED) {
+ ap_update_mtime(r, r->finfo.mtime);
+ ap_set_last_modified(r);
+ ap_set_etag(r);
+ }
+ if (r->header_only) {
+ apr_dir_close(thedir);
+ return 0;
+ }
+
+ /*
+ * If there is no specific ordering defined for this directory,
+ * default to ascending by filename.
+ */
+ keyid = autoindex_conf->default_keyid
+ ? autoindex_conf->default_keyid : K_NAME;
+ direction = autoindex_conf->default_direction
+ ? autoindex_conf->default_direction : D_ASCENDING;
+
+ /*
+ * Figure out what sort of indexing (if any) we're supposed to use.
+ *
+ * If no QUERY_STRING was specified or client query strings have been
+ * explicitly disabled.
+ * If we are ignoring the client, suppress column sorting as well.
+ */
+ if (autoindex_opts & IGNORE_CLIENT) {
+ qstring = NULL;
+ autoindex_opts |= SUPPRESS_COLSORT;
+ colargs = "";
+ }
+ else {
+ char fval[5], vval[5], *ppre = "", *epattern = "";
+ fval[0] = '\0'; vval[0] = '\0';
+ qstring = r->args;
+
+ while (qstring && *qstring) {
+ if (qstring[0] == 'C' && qstring[1] == '='
+ && qstring[2] && strchr(K_VALID, qstring[2])
+ && (qstring[3] == '&' || qstring[3] == ';'
+ || !qstring[3])) {
+ keyid = qstring[2];
+ qstring += qstring[3] ? 4 : 3;
+ }
+ else if (qstring[0] == 'O' && qstring[1] == '='
+ && ((qstring[2] == D_ASCENDING)
+ || (qstring[2] == D_DESCENDING))
+ && (qstring[3] == '&' || qstring[3] == ';'
+ || !qstring[3])) {
+ direction = qstring[2];
+ qstring += qstring[3] ? 4 : 3;
+ }
+ else if (qstring[0] == 'F' && qstring[1] == '='
+ && qstring[2] && strchr("012", qstring[2])
+ && (qstring[3] == '&' || qstring[3] == ';'
+ || !qstring[3])) {
+ if (qstring[2] == '0') {
+ autoindex_opts &= ~(FANCY_INDEXING | TABLE_INDEXING);
+ }
+ else if (qstring[2] == '1') {
+ autoindex_opts = (autoindex_opts | FANCY_INDEXING)
+ & ~TABLE_INDEXING;
+ }
+ else if (qstring[2] == '2') {
+ autoindex_opts |= FANCY_INDEXING | TABLE_INDEXING;
+ }
+ strcpy(fval, ";F= ");
+ fval[3] = qstring[2];
+ qstring += qstring[3] ? 4 : 3;
+ }
+ else if (qstring[0] == 'V' && qstring[1] == '='
+ && (qstring[2] == '0' || qstring[2] == '1')
+ && (qstring[3] == '&' || qstring[3] == ';'
+ || !qstring[3])) {
+ if (qstring[2] == '0') {
+ autoindex_opts &= ~VERSION_SORT;
+ }
+ else if (qstring[2] == '1') {
+ autoindex_opts |= VERSION_SORT;
+ }
+ strcpy(vval, ";V= ");
+ vval[3] = qstring[2];
+ qstring += qstring[3] ? 4 : 3;
+ }
+ else if (qstring[0] == 'P' && qstring[1] == '=') {
+ const char *eos = qstring += 2; /* for efficiency */
+
+ while (*eos && *eos != '&' && *eos != ';') {
+ ++eos;
+ }
+
+ if (eos == qstring) {
+ pstring = NULL;
+ }
+ else {
+ pstring = apr_pstrndup(r->pool, qstring, eos - qstring);
+ if (ap_unescape_url(pstring) != OK) {
+ /* ignore the pattern, if it's bad. */
+ pstring = NULL;
+ }
+ else {
+ ppre = ";P=";
+ /* be correct */
+ epattern = ap_escape_uri(r->pool, pstring);
+ }
+ }
+
+ if (*eos && *++eos) {
+ qstring = eos;
+ }
+ else {
+ qstring = NULL;
+ }
+ }
+ else { /* Syntax error? Ignore the remainder! */
+ qstring = NULL;
+ }
+ }
+ colargs = apr_pstrcat(r->pool, fval, vval, ppre, epattern, NULL);
+ }
+
+ /* Spew HTML preamble */
+ title_endp = title_name + strlen(title_name) - 1;
+
+ while (title_endp > title_name && *title_endp == '/') {
+ *title_endp-- = '\0';
+ }
+
+ emit_head(r, find_header(autoindex_conf, r),
+ autoindex_opts & SUPPRESS_PREAMBLE,
+ autoindex_opts & EMIT_XHTML, title_name);
+
+ /*
+ * Since we don't know how many dir. entries there are, put them into a
+ * linked list and then arrayificate them so qsort can use them.
+ */
+ head = NULL;
+ p = make_parent_entry(autoindex_opts, autoindex_conf, r, keyid, direction);
+ if (p != NULL) {
+ p->next = head;
+ head = p;
+ num_ent++;
+ }
+ fullpath = apr_palloc(r->pool, APR_PATH_MAX);
+ dirpathlen = strlen(name);
+ memcpy(fullpath, name, dirpathlen);
+
+ do {
+ status = apr_dir_read(&dirent, APR_FINFO_MIN | APR_FINFO_NAME, thedir);
+ if (APR_STATUS_IS_INCOMPLETE(status)) {
+ continue; /* ignore un-stat()able files */
+ }
+ else if (status != APR_SUCCESS) {
+ break;
+ }
+
+ /* We want to explode symlinks here. */
+ if (dirent.filetype == APR_LNK) {
+ const char *savename;
+ apr_finfo_t fi;
+ /* We *must* have FNAME. */
+ savename = dirent.name;
+ apr_cpystrn(fullpath + dirpathlen, dirent.name,
+ APR_PATH_MAX - dirpathlen);
+ status = apr_stat(&fi, fullpath,
+ dirent.valid & ~(APR_FINFO_NAME), r->pool);
+ if (status != APR_SUCCESS) {
+ /* Something bad happened, skip this file. */
+ continue;
+ }
+ memcpy(&dirent, &fi, sizeof(fi));
+ dirent.name = savename;
+ dirent.valid |= APR_FINFO_NAME;
+ }
+ p = make_autoindex_entry(&dirent, autoindex_opts, autoindex_conf, r,
+ keyid, direction, pstring);
+ if (p != NULL) {
+ p->next = head;
+ head = p;
+ num_ent++;
+ }
+ } while (1);
+
+ if (num_ent > 0) {
+ ar = (struct ent **) apr_palloc(r->pool,
+ num_ent * sizeof(struct ent *));
+ p = head;
+ x = 0;
+ while (p) {
+ ar[x++] = p;
+ p = p->next;
+ }
+
+ qsort((void *) ar, num_ent, sizeof(struct ent *),
+ (int (*)(const void *, const void *)) dsortf);
+ }
+ output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts,
+ keyid, direction, colargs);
+ apr_dir_close(thedir);
+
+ emit_tail(r, find_readme(autoindex_conf, r),
+ autoindex_opts & SUPPRESS_PREAMBLE);
+
+ return 0;
+}
+
+/* The formal handler... */
+
+static int handle_autoindex(request_rec *r)
+{
+ autoindex_config_rec *d;
+ int allow_opts;
+
+ if(strcmp(r->handler,DIR_MAGIC_TYPE)) {
+ return DECLINED;
+ }
+
+ allow_opts = ap_allow_options(r);
+
+ d = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config,
+ &autoindex_module);
+
+ r->allowed |= (AP_METHOD_BIT << M_GET);
+ if (r->method_number != M_GET) {
+ return DECLINED;
+ }
+
+ /* OK, nothing easy. Trot out the heavy artillery... */
+
+ if (allow_opts & OPT_INDEXES) {
+ int errstatus;
+
+ if ((errstatus = ap_discard_request_body(r)) != OK) {
+ return errstatus;
+ }
+
+ /* KLUDGE --- make the sub_req lookups happen in the right directory.
+ * Fixing this in the sub_req_lookup functions themselves is difficult,
+ * and would probably break virtual includes...
+ */
+
+ if (r->filename[strlen(r->filename) - 1] != '/') {
+ r->filename = apr_pstrcat(r->pool, r->filename, "/", NULL);
+ }
+ return index_directory(r, d);
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Directory index forbidden by rule: %s", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+}
+
+static void register_hooks(apr_pool_t *p)
+{
+ ap_hook_handler(handle_autoindex,NULL,NULL,APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA autoindex_module =
+{
+ STANDARD20_MODULE_STUFF,
+ create_autoindex_config, /* dir config creater */
+ merge_autoindex_configs, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ autoindex_cmds, /* command apr_table_t */
+ register_hooks /* register hooks */
+};
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.dsp b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.dsp
new file mode 100644
index 00000000..da8a9f5c
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.dsp
@@ -0,0 +1,128 @@
+# Microsoft Developer Studio Project File - Name="mod_autoindex" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_autoindex - 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 "mod_autoindex.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 "mod_autoindex.mak" CFG="mod_autoindex - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_autoindex - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_autoindex - 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)" == "mod_autoindex - 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 /Zi /O2 /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_autoindex_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:"Release/mod_autoindex.so" /base:@..\..\os\win32\BaseAddr.ref,mod_autoindex.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Release/mod_autoindex.so" /base:@..\..\os\win32\BaseAddr.ref,mod_autoindex.so /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_autoindex - 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 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_autoindex_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_autoindex.so" /base:@..\..\os\win32\BaseAddr.ref,mod_autoindex.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_autoindex.so" /base:@..\..\os\win32\BaseAddr.ref,mod_autoindex.so
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_autoindex - Win32 Release"
+# Name "mod_autoindex - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_autoindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_autoindex.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\win32ver.awk
+
+!IF "$(CFG)" == "mod_autoindex - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_autoindex.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_autoindex.so "autoindex_module for Apache" ../../include/ap_release.h > .\mod_autoindex.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "mod_autoindex - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_autoindex.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_autoindex.so "autoindex_module for Apache" ../../include/ap_release.h > .\mod_autoindex.rc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.exp b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.exp
new file mode 100644
index 00000000..90f4057e
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.exp
@@ -0,0 +1 @@
+autoindex_module
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.la b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.la
new file mode 100644
index 00000000..139298d2
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.la
@@ -0,0 +1,35 @@
+# mod_autoindex.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_autoindex.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_autoindex.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.lo b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.lo
new file mode 100644
index 00000000..6533eb63
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.lo
@@ -0,0 +1,12 @@
+# mod_autoindex.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object='.libs/mod_autoindex.o'
+
+# Name of the non-PIC object.
+non_pic_object='mod_autoindex.o'
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.o b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.o
new file mode 100644
index 00000000..08725d05
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.c b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.c
new file mode 100644
index 00000000..32902c10
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.c
@@ -0,0 +1,1235 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_script: keeps all script-related ramblings together.
+ *
+ * Compliant to CGI/1.1 spec
+ *
+ * Adapted by rst from original NCSA code by Rob McCool
+ *
+ * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for
+ * custom error responses, and DOCUMENT_ROOT because we found it useful.
+ * It also adds SERVER_ADMIN - useful for scripts to know who to mail when
+ * they fail.
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_thread_proc.h" /* for RLIMIT stuff */
+#include "apr_optional.h"
+#include "apr_buckets.h"
+#include "apr_lib.h"
+#include "apr_poll.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#define CORE_PRIVATE
+
+#include "util_filter.h"
+#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_main.h"
+#include "http_log.h"
+#include "util_script.h"
+#include "ap_mpm.h"
+#include "mod_core.h"
+#include "mod_cgi.h"
+
+module AP_MODULE_DECLARE_DATA cgi_module;
+
+static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgi_pfn_reg_with_ssi;
+static APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgi_pfn_gtv;
+static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgi_pfn_ps;
+static APR_OPTIONAL_FN_TYPE(ap_cgi_build_command) *cgi_build_command;
+
+/* Read and discard the data in the brigade produced by a CGI script */
+static void discard_script_output(apr_bucket_brigade *bb);
+
+/* KLUDGE --- for back-combatibility, we don't have to check ExecCGI
+ * in ScriptAliased directories, which means we need to know if this
+ * request came through ScriptAlias or not... so the Alias module
+ * leaves a note for us.
+ */
+
+static int is_scriptaliased(request_rec *r)
+{
+ const char *t = apr_table_get(r->notes, "alias-forced-type");
+ return t && (!strcasecmp(t, "cgi-script"));
+}
+
+/* Configuration stuff */
+
+#define DEFAULT_LOGBYTES 10385760
+#define DEFAULT_BUFBYTES 1024
+
+typedef struct {
+ const char *logname;
+ long logbytes;
+ apr_size_t bufbytes;
+} cgi_server_conf;
+
+static void *create_cgi_config(apr_pool_t *p, server_rec *s)
+{
+ cgi_server_conf *c =
+ (cgi_server_conf *) apr_pcalloc(p, sizeof(cgi_server_conf));
+
+ c->logname = NULL;
+ c->logbytes = DEFAULT_LOGBYTES;
+ c->bufbytes = DEFAULT_BUFBYTES;
+
+ return c;
+}
+
+static void *merge_cgi_config(apr_pool_t *p, void *basev, void *overridesv)
+{
+ cgi_server_conf *base = (cgi_server_conf *) basev,
+ *overrides = (cgi_server_conf *) overridesv;
+
+ return overrides->logname ? overrides : base;
+}
+
+static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ server_rec *s = cmd->server;
+ cgi_server_conf *conf = ap_get_module_config(s->module_config,
+ &cgi_module);
+
+ conf->logname = ap_server_root_relative(cmd->pool, arg);
+
+ if (!conf->logname) {
+ return apr_pstrcat(cmd->pool, "Invalid ScriptLog path ",
+ arg, NULL);
+ }
+
+ return NULL;
+}
+
+static const char *set_scriptlog_length(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ server_rec *s = cmd->server;
+ cgi_server_conf *conf = ap_get_module_config(s->module_config,
+ &cgi_module);
+
+ conf->logbytes = atol(arg);
+ return NULL;
+}
+
+static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ server_rec *s = cmd->server;
+ cgi_server_conf *conf = ap_get_module_config(s->module_config,
+ &cgi_module);
+
+ conf->bufbytes = atoi(arg);
+ return NULL;
+}
+
+static const command_rec cgi_cmds[] =
+{
+AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
+ "the name of a log for script debugging info"),
+AP_INIT_TAKE1("ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF,
+ "the maximum length (in bytes) of the script debug log"),
+AP_INIT_TAKE1("ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF,
+ "the maximum size (in bytes) to record of a POST request"),
+ {NULL}
+};
+
+static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
+ apr_status_t rv, char *error)
+{
+ apr_file_t *f = NULL;
+ apr_finfo_t finfo;
+ char time_str[APR_CTIME_LEN];
+ int log_flags = rv ? APLOG_ERR : APLOG_ERR;
+
+ ap_log_rerror(APLOG_MARK, log_flags, rv, r,
+ "%s: %s", error, r->filename);
+
+ /* XXX Very expensive mainline case! Open, then getfileinfo! */
+ if (!conf->logname ||
+ ((apr_stat(&finfo, conf->logname,
+ APR_FINFO_SIZE, r->pool) == APR_SUCCESS) &&
+ (finfo.size > conf->logbytes)) ||
+ (apr_file_open(&f, conf->logname,
+ APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT,
+ r->pool) != APR_SUCCESS)) {
+ return ret;
+ }
+
+ /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
+ apr_ctime(time_str, apr_time_now());
+ apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
+ r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+ /* "%% 500 /usr/local/apache/cgi-bin */
+ apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
+
+ apr_file_printf(f, "%%error\n%s\n", error);
+
+ apr_file_close(f);
+ return ret;
+}
+
+/* Soak up stderr from a script and redirect it to the error log.
+ */
+static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err)
+{
+ char argsbuffer[HUGE_STRING_LEN];
+ char *newline;
+ apr_status_t rv;
+
+ while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+ script_err)) == APR_SUCCESS) {
+ newline = strchr(argsbuffer, '\n');
+ if (newline) {
+ *newline = '\0';
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "%s", argsbuffer);
+ }
+
+ return rv;
+}
+
+static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
+ char *dbuf, const char *sbuf, apr_bucket_brigade *bb,
+ apr_file_t *script_err)
+{
+ const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
+ const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
+ char argsbuffer[HUGE_STRING_LEN];
+ apr_file_t *f = NULL;
+ apr_bucket *e;
+ const char *buf;
+ apr_size_t len;
+ apr_status_t rv;
+ int first;
+ int i;
+ apr_finfo_t finfo;
+ char time_str[APR_CTIME_LEN];
+
+ /* XXX Very expensive mainline case! Open, then getfileinfo! */
+ if (!conf->logname ||
+ ((apr_stat(&finfo, conf->logname,
+ APR_FINFO_SIZE, r->pool) == APR_SUCCESS) &&
+ (finfo.size > conf->logbytes)) ||
+ (apr_file_open(&f, conf->logname,
+ APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT,
+ r->pool) != APR_SUCCESS)) {
+ /* Soak up script output */
+ discard_script_output(bb);
+ log_script_err(r, script_err);
+ return ret;
+ }
+
+ /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
+ apr_ctime(time_str, apr_time_now());
+ apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
+ r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+ /* "%% 500 /usr/local/apache/cgi-bin" */
+ apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
+
+ apr_file_puts("%request\n", f);
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (!hdrs[i].key)
+ continue;
+ apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+ }
+ if ((r->method_number == M_POST || r->method_number == M_PUT) &&
+ *dbuf) {
+ apr_file_printf(f, "\n%s\n", dbuf);
+ }
+
+ apr_file_puts("%response\n", f);
+ hdrs_arr = apr_table_elts(r->err_headers_out);
+ hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
+
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (!hdrs[i].key)
+ continue;
+ apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+ }
+
+ if (sbuf && *sbuf)
+ apr_file_printf(f, "%s\n", sbuf);
+
+ first = 1;
+ APR_BRIGADE_FOREACH(e, bb) {
+ if (APR_BUCKET_IS_EOS(e)) {
+ break;
+ }
+ rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS || (len == 0)) {
+ break;
+ }
+ if (first) {
+ apr_file_puts("%stdout\n", f);
+ first = 0;
+ }
+ apr_file_write(f, buf, &len);
+ apr_file_puts("\n", f);
+ }
+
+ if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == APR_SUCCESS) {
+ apr_file_puts("%stderr\n", f);
+ apr_file_puts(argsbuffer, f);
+ while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+ script_err) == APR_SUCCESS) {
+ apr_file_puts(argsbuffer, f);
+ }
+ apr_file_puts("\n", f);
+ }
+
+ apr_brigade_destroy(bb);
+ apr_file_close(script_err);
+
+ apr_file_close(f);
+ return ret;
+}
+
+
+/* This is the special environment used for running the "exec cmd="
+ * variety of SSI directives.
+ */
+static void add_ssi_vars(request_rec *r)
+{
+ apr_table_t *e = r->subprocess_env;
+
+ if (r->path_info && r->path_info[0] != '\0') {
+ request_rec *pa_req;
+
+ apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool,
+ r->path_info));
+
+ pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info),
+ r, NULL);
+ if (pa_req->filename) {
+ apr_table_setn(e, "PATH_TRANSLATED",
+ apr_pstrcat(r->pool, pa_req->filename,
+ pa_req->path_info, NULL));
+ }
+ ap_destroy_sub_req(pa_req);
+ }
+
+ if (r->args) {
+ char *arg_copy = apr_pstrdup(r->pool, r->args);
+
+ apr_table_setn(e, "QUERY_STRING", r->args);
+ ap_unescape_url(arg_copy);
+ apr_table_setn(e, "QUERY_STRING_UNESCAPED",
+ ap_escape_shell_cmd(r->pool, arg_copy));
+ }
+}
+
+static void cgi_child_errfn(apr_pool_t *pool, apr_status_t err,
+ const char *description)
+{
+ apr_file_t *stderr_log;
+ char errbuf[200];
+
+ apr_file_open_stderr(&stderr_log, pool);
+ /* Escape the logged string because it may be something that
+ * came in over the network.
+ */
+ apr_file_printf(stderr_log,
+ "(%d)%s: %s\n",
+ err,
+ apr_strerror(err, errbuf, sizeof(errbuf)),
+#ifdef AP_UNSAFE_ERROR_LOG_UNESCAPED
+ description
+#else
+ ap_escape_logitem(pool, description)
+#endif
+ );
+}
+
+static apr_status_t run_cgi_child(apr_file_t **script_out,
+ apr_file_t **script_in,
+ apr_file_t **script_err,
+ const char *command,
+ const char * const argv[],
+ request_rec *r,
+ apr_pool_t *p,
+ cgi_exec_info_t *e_info)
+{
+ const char * const *env;
+ apr_procattr_t *procattr;
+ apr_proc_t *procnew;
+ apr_status_t rc = APR_SUCCESS;
+
+#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \
+ defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
+
+ core_dir_config *conf = ap_get_module_config(r->per_dir_config,
+ &core_module);
+#endif
+
+#ifdef DEBUG_CGI
+#ifdef OS2
+ /* Under OS/2 need to use device con. */
+ FILE *dbg = fopen("con", "w");
+#else
+ FILE *dbg = fopen("/dev/tty", "w");
+#endif
+ int i;
+#endif
+
+ RAISE_SIGSTOP(CGI_CHILD);
+#ifdef DEBUG_CGI
+ fprintf(dbg, "Attempting to exec %s as CGI child (argv0 = %s)\n",
+ r->filename, argv[0]);
+#endif
+
+ env = (const char * const *)ap_create_environment(p, r->subprocess_env);
+
+#ifdef DEBUG_CGI
+ fprintf(dbg, "Environment: \n");
+ for (i = 0; env[i]; ++i)
+ fprintf(dbg, "'%s'\n", env[i]);
+#endif
+
+ /* Transmute ourselves into the script.
+ * NB only ISINDEX scripts get decoded arguments.
+ */
+ if (((rc = apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_io_set(procattr,
+ e_info->in_pipe,
+ e_info->out_pipe,
+ e_info->err_pipe)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_dir_set(procattr,
+ ap_make_dirstr_parent(r->pool,
+ r->filename))) != APR_SUCCESS) ||
+#ifdef RLIMIT_CPU
+ ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_CPU,
+ conf->limit_cpu)) != APR_SUCCESS) ||
+#endif
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+ ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_MEM,
+ conf->limit_mem)) != APR_SUCCESS) ||
+#endif
+#ifdef RLIMIT_NPROC
+ ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC,
+ conf->limit_nproc)) != APR_SUCCESS) ||
+#endif
+ ((rc = apr_procattr_cmdtype_set(procattr,
+ e_info->cmd_type)) != APR_SUCCESS) ||
+
+ ((rc = apr_procattr_detach_set(procattr,
+ e_info->detached & AP_PROC_DETACHED)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_addrspace_set(procattr,
+ (e_info->detached & AP_PROC_NEWADDRSPACE) ? 1 : 0)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_child_errfn_set(procattr, cgi_child_errfn)) != APR_SUCCESS)) {
+ /* Something bad happened, tell the world. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
+ "couldn't set child process attributes: %s", r->filename);
+ }
+ else {
+ procnew = apr_pcalloc(p, sizeof(*procnew));
+ if (e_info->prog_type == RUN_AS_SSI) {
+ SPLIT_AND_PASS_PRETAG_BUCKETS(*(e_info->bb), e_info->ctx,
+ e_info->next, rc);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+ }
+
+ rc = ap_os_create_privileged_process(r, procnew, command, argv, env,
+ procattr, p);
+
+ if (rc != APR_SUCCESS) {
+ /* Bad things happened. Everyone should have cleaned up. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rc, r,
+ "couldn't create child process: %d: %s", rc,
+ apr_filename_of_pathname(r->filename));
+ }
+ else {
+ apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
+
+ *script_in = procnew->out;
+ if (!*script_in)
+ return APR_EBADF;
+ apr_file_pipe_timeout_set(*script_in, r->server->timeout);
+
+ if (e_info->prog_type == RUN_AS_CGI) {
+ *script_out = procnew->in;
+ if (!*script_out)
+ return APR_EBADF;
+ apr_file_pipe_timeout_set(*script_out, r->server->timeout);
+
+ *script_err = procnew->err;
+ if (!*script_err)
+ return APR_EBADF;
+ apr_file_pipe_timeout_set(*script_err, r->server->timeout);
+ }
+ }
+ }
+#ifdef DEBUG_CGI
+ fclose(dbg);
+#endif
+ return (rc);
+}
+
+
+static apr_status_t default_build_command(const char **cmd, const char ***argv,
+ request_rec *r, apr_pool_t *p,
+ cgi_exec_info_t *e_info)
+{
+ int numwords, x, idx;
+ char *w;
+ const char *args = NULL;
+
+ if (e_info->process_cgi) {
+ *cmd = r->filename;
+ /* Do not process r->args if they contain an '=' assignment
+ */
+ if (r->args && r->args[0] && !ap_strchr_c(r->args, '=')) {
+ args = r->args;
+ }
+ }
+
+ if (!args) {
+ numwords = 1;
+ }
+ else {
+ /* count the number of keywords */
+ for (x = 0, numwords = 2; args[x]; x++) {
+ if (args[x] == '+') {
+ ++numwords;
+ }
+ }
+ }
+ /* Everything is - 1 to account for the first parameter
+ * which is the program name.
+ */
+ if (numwords > APACHE_ARG_MAX - 1) {
+ numwords = APACHE_ARG_MAX - 1; /* Truncate args to prevent overrun */
+ }
+ *argv = apr_palloc(p, (numwords + 2) * sizeof(char *));
+ (*argv)[0] = *cmd;
+ for (x = 1, idx = 1; x < numwords; x++) {
+ w = ap_getword_nulls(p, &args, '+');
+ ap_unescape_url(w);
+ (*argv)[idx++] = ap_escape_shell_cmd(p, w);
+ }
+ (*argv)[idx] = NULL;
+
+ return APR_SUCCESS;
+}
+
+static void discard_script_output(apr_bucket_brigade *bb)
+{
+ apr_bucket *e;
+ const char *buf;
+ apr_size_t len;
+ apr_status_t rv;
+ APR_BRIGADE_FOREACH(e, bb) {
+ if (APR_BUCKET_IS_EOS(e)) {
+ break;
+ }
+ rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+ break;
+ }
+ }
+}
+
+#if APR_FILES_AS_SOCKETS
+
+/* A CGI bucket type is needed to catch any output to stderr from the
+ * script; see PR 22030. */
+static const apr_bucket_type_t bucket_type_cgi;
+
+struct cgi_bucket_data {
+ apr_pollset_t *pollset;
+ request_rec *r;
+};
+
+/* Create a CGI bucket using pipes from script stdout 'out'
+ * and stderr 'err', for request 'r'. */
+static apr_bucket *cgi_bucket_create(request_rec *r,
+ apr_file_t *out, apr_file_t *err,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+ apr_status_t rv;
+ apr_pollfd_t fd;
+ struct cgi_bucket_data *data = apr_palloc(r->pool, sizeof *data);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ b->type = &bucket_type_cgi;
+ b->length = (apr_size_t)(-1);
+ b->start = -1;
+
+ /* Create the pollset */
+ rv = apr_pollset_create(&data->pollset, 2, r->pool, 0);
+ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
+
+ fd.desc_type = APR_POLL_FILE;
+ fd.reqevents = APR_POLLIN;
+ fd.p = r->pool;
+ fd.desc.f = out; /* script's stdout */
+ fd.client_data = (void *)1;
+ rv = apr_pollset_add(data->pollset, &fd);
+ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
+
+ fd.desc.f = err; /* script's stderr */
+ fd.client_data = (void *)2;
+ rv = apr_pollset_add(data->pollset, &fd);
+ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
+
+ data->r = r;
+ b->data = data;
+ return b;
+}
+
+/* Create a duplicate CGI bucket using given bucket data */
+static apr_bucket *cgi_bucket_dup(struct cgi_bucket_data *data,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ b->type = &bucket_type_cgi;
+ b->length = (apr_size_t)(-1);
+ b->start = -1;
+ b->data = data;
+ return b;
+}
+
+/* Handle stdout from CGI child. Duplicate of logic from the _read
+ * method of the real APR pipe bucket implementation. */
+static apr_status_t cgi_read_stdout(apr_bucket *a, apr_file_t *out,
+ const char **str, apr_size_t *len)
+{
+ char *buf;
+ apr_status_t rv;
+
+ *str = NULL;
+ *len = APR_BUCKET_BUFF_SIZE;
+ buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
+
+ rv = apr_file_read(out, buf, len);
+
+ if (rv != APR_SUCCESS && rv != APR_EOF) {
+ apr_bucket_free(buf);
+ return rv;
+ }
+
+ if (*len > 0) {
+ struct cgi_bucket_data *data = a->data;
+ apr_bucket_heap *h;
+
+ /* Change the current bucket to refer to what we read */
+ a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
+ h = a->data;
+ h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
+ *str = buf;
+ APR_BUCKET_INSERT_AFTER(a, cgi_bucket_dup(data, a->list));
+ }
+ else {
+ apr_bucket_free(buf);
+ a = apr_bucket_immortal_make(a, "", 0);
+ *str = a->data;
+ }
+ return rv;
+}
+
+/* Read method of CGI bucket: polls on stderr and stdout of the child,
+ * sending any stderr output immediately away to the error log. */
+static apr_status_t cgi_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ struct cgi_bucket_data *data = b->data;
+ apr_interval_time_t timeout;
+ apr_status_t rv;
+ int gotdata = 0;
+
+ timeout = block == APR_NONBLOCK_READ ? 0 : data->r->server->timeout;
+
+ do {
+ const apr_pollfd_t *results;
+ apr_int32_t num;
+
+ rv = apr_pollset_poll(data->pollset, timeout, &num, &results);
+ if (APR_STATUS_IS_TIMEUP(rv)) {
+ return timeout == 0 ? APR_EAGAIN : rv;
+ }
+ else if (APR_STATUS_IS_EINTR(rv)) {
+ continue;
+ }
+ else if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r,
+ "poll failed waiting for CGI child");
+ return rv;
+ }
+
+ for (; num; num--, results++) {
+ if (results[0].client_data == (void *)1) {
+ /* stdout */
+ rv = cgi_read_stdout(b, results[0].desc.f, str, len);
+ if (APR_STATUS_IS_EOF(rv)) {
+ rv = APR_SUCCESS;
+ }
+ gotdata = 1;
+ } else {
+ /* stderr */
+ apr_status_t rv2 = log_script_err(data->r, results[0].desc.f);
+ if (APR_STATUS_IS_EOF(rv2)) {
+ apr_pollset_remove(data->pollset, &results[0]);
+ }
+ }
+ }
+
+ } while (!gotdata);
+
+ return rv;
+}
+
+static const apr_bucket_type_t bucket_type_cgi = {
+ "CGI", 5, APR_BUCKET_DATA,
+ apr_bucket_destroy_noop,
+ cgi_bucket_read,
+ apr_bucket_setaside_notimpl,
+ apr_bucket_split_notimpl,
+ apr_bucket_copy_notimpl
+};
+
+#endif
+
+static int cgi_handler(request_rec *r)
+{
+ int nph;
+ apr_size_t dbpos = 0;
+ const char *argv0;
+ const char *command;
+ const char **argv;
+ char *dbuf = NULL;
+ apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL;
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ int is_included;
+ int seen_eos, child_stopped_reading;
+ apr_pool_t *p;
+ cgi_server_conf *conf;
+ apr_status_t rv;
+ cgi_exec_info_t e_info;
+ conn_rec *c = r->connection;
+
+ if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script"))
+ return DECLINED;
+
+ is_included = !strcmp(r->protocol, "INCLUDED");
+
+ p = r->main ? r->main->pool : r->pool;
+
+ argv0 = apr_filename_of_pathname(r->filename);
+ nph = !(strncmp(argv0, "nph-", 4));
+ conf = ap_get_module_config(r->server->module_config, &cgi_module);
+
+ if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "Options ExecCGI is off in this directory");
+ if (nph && is_included)
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "attempt to include NPH CGI script");
+
+ if (r->finfo.filetype == 0)
+ return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,
+ "script not found or unable to stat");
+ if (r->finfo.filetype == APR_DIR)
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "attempt to invoke directory as script");
+
+ if ((r->used_path_info == AP_REQ_REJECT_PATH_INFO) &&
+ r->path_info && *r->path_info)
+ {
+ /* default to accept */
+ return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,
+ "AcceptPathInfo off disallows user's path");
+ }
+/*
+ if (!ap_suexec_enabled) {
+ if (!ap_can_exec(&r->finfo))
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "file permissions deny server execution");
+ }
+
+*/
+ ap_add_common_vars(r);
+ ap_add_cgi_vars(r);
+
+ e_info.process_cgi = 1;
+ e_info.cmd_type = APR_PROGRAM;
+ e_info.detached = 0;
+ e_info.in_pipe = APR_CHILD_BLOCK;
+ e_info.out_pipe = APR_CHILD_BLOCK;
+ e_info.err_pipe = APR_CHILD_BLOCK;
+ e_info.prog_type = RUN_AS_CGI;
+ e_info.bb = NULL;
+ e_info.ctx = NULL;
+ e_info.next = NULL;
+
+ /* build the command line */
+ if ((rv = cgi_build_command(&command, &argv, r, p, &e_info)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "don't know how to spawn child process: %s",
+ r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* run the script in its own process */
+ if ((rv = run_cgi_child(&script_out, &script_in, &script_err,
+ command, argv, r, p, &e_info)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "couldn't spawn child process: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* Transfer any put/post args, CERN style...
+ * Note that we already ignore SIGPIPE in the core server.
+ */
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+ seen_eos = 0;
+ child_stopped_reading = 0;
+ if (conf->logname) {
+ dbuf = apr_palloc(r->pool, conf->bufbytes + 1);
+ dbpos = 0;
+ }
+ do {
+ apr_bucket *bucket;
+
+ rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
+ APR_BLOCK_READ, HUGE_STRING_LEN);
+
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "Error reading request entity data");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ APR_BRIGADE_FOREACH(bucket, bb) {
+ const char *data;
+ apr_size_t len;
+
+ if (APR_BUCKET_IS_EOS(bucket)) {
+ seen_eos = 1;
+ break;
+ }
+
+ /* We can't do much with this. */
+ if (APR_BUCKET_IS_FLUSH(bucket)) {
+ continue;
+ }
+
+ /* If the child stopped, we still must read to EOS. */
+ if (child_stopped_reading) {
+ continue;
+ }
+
+ /* read */
+ apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
+
+ if (conf->logname && dbpos < conf->bufbytes) {
+ int cursize;
+
+ if ((dbpos + len) > conf->bufbytes) {
+ cursize = conf->bufbytes - dbpos;
+ }
+ else {
+ cursize = len;
+ }
+ memcpy(dbuf + dbpos, data, cursize);
+ dbpos += cursize;
+ }
+
+ /* Keep writing data to the child until done or too much time
+ * elapses with no progress or an error occurs.
+ */
+ rv = apr_file_write_full(script_out, data, len, NULL);
+
+ if (rv != APR_SUCCESS) {
+ /* silly script stopped reading, soak up remaining message */
+ child_stopped_reading = 1;
+ }
+ }
+ apr_brigade_cleanup(bb);
+ }
+ while (!seen_eos);
+
+ if (conf->logname) {
+ dbuf[dbpos] = '\0';
+ }
+ /* Is this flush really needed? */
+ apr_file_flush(script_out);
+ apr_file_close(script_out);
+
+ AP_DEBUG_ASSERT(script_in != NULL);
+
+ apr_brigade_cleanup(bb);
+
+#if APR_FILES_AS_SOCKETS
+ apr_file_pipe_timeout_set(script_in, 0);
+ apr_file_pipe_timeout_set(script_err, 0);
+
+ b = cgi_bucket_create(r, script_in, script_err, c->bucket_alloc);
+#else
+ b = apr_bucket_pipe_create(script_in, c->bucket_alloc);
+#endif
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+
+ /* Handle script return... */
+ if (!nph) {
+ const char *location;
+ char sbuf[MAX_STRING_LEN];
+ int ret;
+
+ if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) {
+ return log_script(r, conf, ret, dbuf, sbuf, bb, script_err);
+ }
+
+ location = apr_table_get(r->headers_out, "Location");
+
+ if (location && location[0] == '/' && r->status == 200) {
+ discard_script_output(bb);
+ apr_brigade_destroy(bb);
+ apr_file_pipe_timeout_set(script_err, r->server->timeout);
+ log_script_err(r, script_err);
+ /* This redirect needs to be a GET no matter what the original
+ * method was.
+ */
+ r->method = apr_pstrdup(r->pool, "GET");
+ r->method_number = M_GET;
+
+ /* We already read the message body (if any), so don't allow
+ * the redirected request to think it has one. We can ignore
+ * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
+ */
+ apr_table_unset(r->headers_in, "Content-Length");
+
+ ap_internal_redirect_handler(location, r);
+ return OK;
+ }
+ else if (location && r->status == 200) {
+ /* XX Note that if a script wants to produce its own Redirect
+ * body, it now has to explicitly *say* "Status: 302"
+ */
+ discard_script_output(bb);
+ apr_brigade_destroy(bb);
+ return HTTP_MOVED_TEMPORARILY;
+ }
+
+ rv = ap_pass_brigade(r->output_filters, bb);
+ }
+ else /* nph */ {
+ struct ap_filter_t *cur;
+
+ /* get rid of all filters up through protocol... since we
+ * haven't parsed off the headers, there is no way they can
+ * work
+ */
+
+ cur = r->proto_output_filters;
+ while (cur && cur->frec->ftype < AP_FTYPE_CONNECTION) {
+ cur = cur->next;
+ }
+ r->output_filters = r->proto_output_filters = cur;
+
+ rv = ap_pass_brigade(r->output_filters, bb);
+ }
+
+ /* don't soak up script output if errors occurred writing it
+ * out... otherwise, we prolong the life of the script when the
+ * connection drops or we stopped sending output for some other
+ * reason */
+ if (rv == APR_SUCCESS && !r->connection->aborted) {
+ apr_file_pipe_timeout_set(script_err, r->server->timeout);
+ log_script_err(r, script_err);
+ }
+
+ apr_file_close(script_err);
+
+ return OK; /* NOT r->status, even if it has changed. */
+}
+
+/*============================================================================
+ *============================================================================
+ * This is the beginning of the cgi filter code moved from mod_include. This
+ * is the code required to handle the "exec" SSI directive.
+ *============================================================================
+ *============================================================================*/
+static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
+ apr_bucket *head_ptr, apr_bucket **inserted_head)
+{
+ request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
+ int rr_status;
+ apr_bucket *tmp_buck, *tmp2_buck;
+
+ if (rr->status != HTTP_OK) {
+ ap_destroy_sub_req(rr);
+ return -1;
+ }
+
+ /* No hardwired path info or query allowed */
+
+ if ((rr->path_info && rr->path_info[0]) || rr->args) {
+ ap_destroy_sub_req(rr);
+ return -1;
+ }
+ if (rr->finfo.filetype != APR_REG) {
+ ap_destroy_sub_req(rr);
+ return -1;
+ }
+
+ /* Script gets parameters of the *document*, for back compatibility */
+
+ rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */
+ rr->args = r->args;
+
+ /* Force sub_req to be treated as a CGI request, even if ordinary
+ * typing rules would have called it something else.
+ */
+
+ ap_set_content_type(rr, CGI_MAGIC_TYPE);
+
+ /* Run it. */
+
+ rr_status = ap_run_sub_req(rr);
+ if (ap_is_HTTP_REDIRECT(rr_status)) {
+ apr_size_t len_loc;
+ const char *location = apr_table_get(rr->headers_out, "Location");
+ conn_rec *c = r->connection;
+
+ location = ap_escape_html(rr->pool, location);
+ len_loc = strlen(location);
+
+ /* XXX: if most of this stuff is going to get copied anyway,
+ * it'd be more efficient to pstrcat it into a single pool buffer
+ * and a single pool bucket */
+
+ tmp_buck = apr_bucket_immortal_create("<A HREF=\"",
+ sizeof("<A HREF=\"") - 1,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
+ tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+ tmp2_buck = apr_bucket_immortal_create("\">", sizeof("\">") - 1,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+ tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+ tmp2_buck = apr_bucket_immortal_create("</A>", sizeof("</A>") - 1,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+
+ if (*inserted_head == NULL) {
+ *inserted_head = tmp_buck;
+ }
+ }
+
+ ap_destroy_sub_req(rr);
+
+ return 0;
+}
+
+
+static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb,
+ const char *command, request_rec *r, ap_filter_t *f)
+{
+ cgi_exec_info_t e_info;
+ const char **argv;
+ apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL;
+ apr_bucket_brigade *bcgi;
+ apr_bucket *b;
+ apr_status_t rv;
+
+ add_ssi_vars(r);
+
+ e_info.process_cgi = 0;
+ e_info.cmd_type = APR_SHELLCMD;
+ e_info.detached = 0;
+ e_info.in_pipe = APR_NO_PIPE;
+ e_info.out_pipe = APR_FULL_BLOCK;
+ e_info.err_pipe = APR_NO_PIPE;
+ e_info.prog_type = RUN_AS_SSI;
+ e_info.bb = bb;
+ e_info.ctx = ctx;
+ e_info.next = f->next;
+
+ if ((rv = cgi_build_command(&command, &argv, r, r->pool, &e_info)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "don't know how to spawn cmd child process: %s",
+ r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /* run the script in its own process */
+ if ((rv = run_cgi_child(&script_out, &script_in, &script_err,
+ command, argv, r, r->pool,
+ &e_info)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "couldn't spawn child process: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ bcgi = apr_brigade_create(r->pool, f->c->bucket_alloc);
+ b = apr_bucket_pipe_create(script_in, f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bcgi, b);
+ ap_pass_brigade(f->next, bcgi);
+
+ /* We can't close the pipe here, because we may return before the
+ * full CGI has been sent to the network. That's okay though,
+ * because we can rely on the pool to close the pipe for us.
+ */
+
+ return 0;
+}
+
+static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb,
+ request_rec *r, ap_filter_t *f, apr_bucket *head_ptr,
+ apr_bucket **inserted_head)
+{
+ char *tag = NULL;
+ char *tag_val = NULL;
+ char *file = r->filename;
+ apr_bucket *tmp_buck;
+ char parsed_string[MAX_STRING_LEN];
+
+ *inserted_head = NULL;
+ if (ctx->flags & FLAG_PRINTING) {
+ if (ctx->flags & FLAG_NO_EXEC) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "exec used but not allowed in %s", r->filename);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
+ }
+ else {
+ while (1) {
+ cgi_pfn_gtv(ctx, &tag, &tag_val, 1);
+ if (tag_val == NULL) {
+ if (tag == NULL) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ }
+ if (!strcmp(tag, "cmd")) {
+ cgi_pfn_ps(r, ctx, tag_val, parsed_string,
+ sizeof(parsed_string), 1);
+ if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "execution failure for parameter \"%s\" "
+ "to tag exec in file %s", tag, r->filename);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr,
+ *inserted_head);
+ }
+ }
+ else if (!strcmp(tag, "cgi")) {
+ apr_status_t retval = APR_SUCCESS;
+
+ cgi_pfn_ps(r, ctx, tag_val, parsed_string,
+ sizeof(parsed_string), 0);
+
+ SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next, retval);
+ if (retval != APR_SUCCESS) {
+ return retval;
+ }
+
+ if (include_cgi(parsed_string, r, f->next, head_ptr,
+ inserted_head) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "invalid CGI ref \"%s\" in %s",
+ tag_val, file);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr,
+ *inserted_head);
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "unknown parameter \"%s\" to tag exec in %s",
+ tag, file);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr,
+ *inserted_head);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*============================================================================
+ *============================================================================
+ * This is the end of the cgi filter code moved from mod_include.
+ *============================================================================
+ *============================================================================*/
+
+
+static int cgi_post_config(apr_pool_t *p, apr_pool_t *plog,
+ apr_pool_t *ptemp, server_rec *s)
+{
+ cgi_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
+ cgi_pfn_gtv = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);
+ cgi_pfn_ps = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);
+
+ if ((cgi_pfn_reg_with_ssi) && (cgi_pfn_gtv) && (cgi_pfn_ps)) {
+ /* Required by mod_include filter. This is how mod_cgi registers
+ * with mod_include to provide processing of the exec directive.
+ */
+ cgi_pfn_reg_with_ssi("exec", handle_exec);
+ }
+
+ /* This is the means by which unusual (non-unix) os's may find alternate
+ * means to run a given command (e.g. shebang/registry parsing on Win32)
+ */
+ cgi_build_command = APR_RETRIEVE_OPTIONAL_FN(ap_cgi_build_command);
+ if (!cgi_build_command) {
+ cgi_build_command = default_build_command;
+ }
+ return OK;
+}
+
+static void register_hooks(apr_pool_t *p)
+{
+ static const char * const aszPre[] = { "mod_include.c", NULL };
+ ap_hook_handler(cgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_post_config(cgi_post_config, aszPre, NULL, APR_HOOK_REALLY_FIRST);
+}
+
+module AP_MODULE_DECLARE_DATA cgi_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ create_cgi_config, /* server config */
+ merge_cgi_config, /* merge server config */
+ cgi_cmds, /* command apr_table_t */
+ register_hooks /* register hooks */
+};
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.dsp b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.dsp
new file mode 100644
index 00000000..02167c19
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.dsp
@@ -0,0 +1,132 @@
+# Microsoft Developer Studio Project File - Name="mod_cgi" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_cgi - 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 "mod_cgi.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 "mod_cgi.mak" CFG="mod_cgi - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_cgi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_cgi - 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)" == "mod_cgi - 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 /Zi /O2 /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_cgi_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:"Release/mod_cgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_cgi.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Release/mod_cgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_cgi.so /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_cgi - 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 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_cgi_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_cgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_cgi.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_cgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_cgi.so
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_cgi - Win32 Release"
+# Name "mod_cgi - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_cgi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_cgi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_cgi.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\win32ver.awk
+
+!IF "$(CFG)" == "mod_cgi - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_cgi.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_cgi.so "cgi_module for Apache" ../../include/ap_release.h > .\mod_cgi.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "mod_cgi - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_cgi.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_cgi.so "cgi_module for Apache" ../../include/ap_release.h > .\mod_cgi.rc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.exp b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.exp
new file mode 100644
index 00000000..96ea0c23
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.exp
@@ -0,0 +1 @@
+cgi_module
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.h b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.h
new file mode 100644
index 00000000..9a54895a
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgi.h
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MOD_CGI_H
+#define _MOD_CGI_H 1
+
+#include "mod_include.h"
+
+#define AP_PROC_DETACHED 1
+#define AP_PROC_NEWADDRSPACE 2
+
+typedef enum {RUN_AS_SSI, RUN_AS_CGI} prog_types;
+
+typedef struct {
+ apr_int32_t in_pipe;
+ apr_int32_t out_pipe;
+ apr_int32_t err_pipe;
+ int process_cgi;
+ apr_cmdtype_e cmd_type;
+ apr_int32_t detached; /* used as a bitfield for detached_ & addrspace_set, */
+ /* when initializing apr_proc_attr structure */
+ prog_types prog_type;
+ apr_bucket_brigade **bb;
+ include_ctx_t *ctx;
+ ap_filter_t *next;
+} cgi_exec_info_t;
+
+/**
+ * Registerable optional function to override CGI behavior;
+ * Reprocess the command and arguments to execute the given CGI script.
+ * @param cmd Pointer to the command to execute (may be overridden)
+ * @param argv Pointer to the arguments to pass (may be overridden)
+ * @param r The current request
+ * @param p The pool to allocate correct cmd/argv elements within.
+ * @param process_cgi Set true if processing r->filename and r->args
+ * as a CGI invocation, otherwise false
+ * @param type Set to APR_SHELLCMD or APR_PROGRAM on entry, may be
+ * changed to invoke the program with alternate semantics.
+ * @param detach Should the child start in detached state? Default is no.
+ * @remark This callback may be registered by the os-specific module
+ * to correct the command and arguments for apr_proc_create invocation
+ * on a given os. mod_cgi will call the function if registered.
+ */
+APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_cgi_build_command,
+ (const char **cmd, const char ***argv,
+ request_rec *r, apr_pool_t *p,
+ cgi_exec_info_t *e_info));
+
+#endif /* _MOD_CGI_H */
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.c b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.c
new file mode 100644
index 00000000..55ac3b04
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.c
@@ -0,0 +1,1744 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * http_script: keeps all script-related ramblings together.
+ *
+ * Compliant to cgi/1.1 spec
+ *
+ * Adapted by rst from original NCSA code by Rob McCool
+ *
+ * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for
+ * custom error responses, and DOCUMENT_ROOT because we found it useful.
+ * It also adds SERVER_ADMIN - useful for scripts to know who to mail when
+ * they fail.
+ */
+
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_general.h"
+#include "apr_file_io.h"
+#include "apr_portable.h"
+#include "apr_buckets.h"
+#include "apr_optional.h"
+#include "apr_signal.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if APR_HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#define CORE_PRIVATE
+
+#include "util_filter.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_request.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "util_script.h"
+#include "ap_mpm.h"
+#include "unixd.h"
+#include "mod_suexec.h"
+#include "../filters/mod_include.h"
+
+#include "mod_core.h"
+
+
+/* ### should be tossed in favor of APR */
+#include <sys/stat.h>
+#include <sys/un.h> /* for sockaddr_un */
+
+
+module AP_MODULE_DECLARE_DATA cgid_module;
+
+static int cgid_start(apr_pool_t *p, server_rec *main_server, apr_proc_t *procnew);
+static int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server);
+static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
+ ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head);
+
+static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgid_pfn_reg_with_ssi;
+static APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgid_pfn_gtv;
+static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgid_pfn_ps;
+
+static apr_pool_t *pcgi = NULL;
+static int total_modules = 0;
+static pid_t daemon_pid;
+static int daemon_should_exit = 0;
+static server_rec *root_server = NULL;
+static apr_pool_t *root_pool = NULL;
+static ap_unix_identity_t empty_ugid = { (uid_t)-1, (gid_t)-1, -1 };
+
+/* Read and discard the data in the brigade produced by a CGI script */
+static void discard_script_output(apr_bucket_brigade *bb);
+
+/* This doer will only ever be called when we are sure that we have
+ * a valid ugid.
+ */
+static ap_unix_identity_t *cgid_suexec_id_doer(const request_rec *r)
+{
+ return (ap_unix_identity_t *)
+ ap_get_module_config(r->request_config, &cgid_module);
+}
+
+/* KLUDGE --- for back-combatibility, we don't have to check ExecCGI
+ * in ScriptAliased directories, which means we need to know if this
+ * request came through ScriptAlias or not... so the Alias module
+ * leaves a note for us.
+ */
+
+static int is_scriptaliased(request_rec *r)
+{
+ const char *t = apr_table_get(r->notes, "alias-forced-type");
+ return t && (!strcasecmp(t, "cgi-script"));
+}
+
+/* Configuration stuff */
+
+#define DEFAULT_LOGBYTES 10385760
+#define DEFAULT_BUFBYTES 1024
+#define DEFAULT_SOCKET DEFAULT_REL_RUNTIMEDIR "/cgisock"
+
+#define CGI_REQ 1
+#define SSI_REQ 2
+#define GETPID_REQ 3 /* get the pid of script created for prior request */
+
+#define ERRFN_USERDATA_KEY "CGIDCHILDERRFN"
+
+/* DEFAULT_CGID_LISTENBACKLOG controls the max depth on the unix socket's
+ * pending connection queue. If a bunch of cgi requests arrive at about
+ * the same time, connections from httpd threads/processes will back up
+ * in the queue while the cgid process slowly forks off a child to process
+ * each connection on the unix socket. If the queue is too short, the
+ * httpd process will get ECONNREFUSED when trying to connect.
+ */
+#ifndef DEFAULT_CGID_LISTENBACKLOG
+#define DEFAULT_CGID_LISTENBACKLOG 100
+#endif
+
+/* DEFAULT_CONNECT_ATTEMPTS controls how many times we'll try to connect
+ * to the cgi daemon from the thread/process handling the cgi request.
+ * Generally we want to retry when we get ECONNREFUSED since it is
+ * probably because the listen queue is full. We need to try harder so
+ * the client doesn't see it as a 503 error.
+ *
+ * Set this to 0 to continually retry until the connect works or Apache
+ * terminates.
+ */
+#ifndef DEFAULT_CONNECT_ATTEMPTS
+#define DEFAULT_CONNECT_ATTEMPTS 15
+#endif
+
+typedef struct {
+ const char *sockname;
+ const char *logname;
+ long logbytes;
+ int bufbytes;
+} cgid_server_conf;
+
+typedef struct {
+ int req_type; /* request type (CGI_REQ, SSI_REQ, etc.) */
+ unsigned long conn_id; /* connection id; daemon uses this as a hash value
+ * to find the script pid when it is time for that
+ * process to be cleaned up
+ */
+ int core_module_index;
+ int env_count;
+ ap_unix_identity_t ugid;
+ apr_size_t filename_len;
+ apr_size_t argv0_len;
+ apr_size_t uri_len;
+ apr_size_t args_len;
+ int loglevel; /* to stuff in server_rec */
+} cgid_req_t;
+
+/* This routine is called to create the argument list to be passed
+ * to the CGI script. When suexec is enabled, the suexec path, user, and
+ * group are the first three arguments to be passed; if not, all three
+ * must be NULL. The query info is split into separate arguments, where
+ * "+" is the separator between keyword arguments.
+ *
+ * Do not process the args if they containing an '=' assignment.
+ */
+static char **create_argv(apr_pool_t *p, char *path, char *user, char *group,
+ char *av0, const char *args)
+{
+ int x, numwords;
+ char **av;
+ char *w;
+ int idx = 0;
+
+ if (ap_strchr_c(args, '=')) {
+ numwords = 0;
+ }
+ else {
+ /* count the number of keywords */
+
+ for (x = 0, numwords = 1; args[x]; x++) {
+ if (args[x] == '+') {
+ ++numwords;
+ }
+ }
+ }
+
+ if (numwords > APACHE_ARG_MAX - 5) {
+ numwords = APACHE_ARG_MAX - 5; /* Truncate args to prevent overrun */
+ }
+ av = (char **) apr_pcalloc(p, (numwords + 5) * sizeof(char *));
+
+ if (path) {
+ av[idx++] = path;
+ }
+ if (user) {
+ av[idx++] = user;
+ }
+ if (group) {
+ av[idx++] = group;
+ }
+
+ av[idx++] = apr_pstrdup(p, av0);
+
+ for (x = 1; x <= numwords; x++) {
+ w = ap_getword_nulls(p, &args, '+');
+ if (strcmp(w, "")) {
+ ap_unescape_url(w);
+ av[idx++] = ap_escape_shell_cmd(p, w);
+ }
+ }
+ av[idx] = NULL;
+ return av;
+}
+
+#if APR_HAS_OTHER_CHILD
+static void cgid_maint(int reason, void *data, apr_wait_t status)
+{
+ apr_proc_t *proc = data;
+ int mpm_state;
+ int stopping;
+
+ switch (reason) {
+ case APR_OC_REASON_DEATH:
+ apr_proc_other_child_unregister(data);
+ /* If apache is not terminating or restarting,
+ * restart the cgid daemon
+ */
+ stopping = 1; /* if MPM doesn't support query,
+ * assume we shouldn't restart daemon
+ */
+ if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state) == APR_SUCCESS &&
+ mpm_state != AP_MPMQ_STOPPING) {
+ stopping = 0;
+ }
+ if (!stopping) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "cgid daemon process died, restarting");
+ cgid_start(root_pool, root_server, proc);
+ }
+ break;
+ case APR_OC_REASON_RESTART:
+ /* don't do anything; server is stopping or restarting */
+ apr_proc_other_child_unregister(data);
+ break;
+ case APR_OC_REASON_LOST:
+ /* Restart the child cgid daemon process */
+ apr_proc_other_child_unregister(data);
+ cgid_start(root_pool, root_server, proc);
+ break;
+ case APR_OC_REASON_UNREGISTER:
+ /* we get here when pcgi is cleaned up; pcgi gets cleaned
+ * up when pconf gets cleaned up
+ */
+ kill(proc->pid, SIGHUP); /* send signal to daemon telling it to die */
+ break;
+ }
+}
+#endif
+
+/* deal with incomplete reads and signals
+ * assume you really have to read buf_size bytes
+ */
+static apr_status_t sock_read(int fd, void *vbuf, size_t buf_size)
+{
+ char *buf = vbuf;
+ int rc;
+ size_t bytes_read = 0;
+
+ do {
+ do {
+ rc = read(fd, buf + bytes_read, buf_size - bytes_read);
+ } while (rc < 0 && errno == EINTR);
+ switch(rc) {
+ case -1:
+ return errno;
+ case 0: /* unexpected */
+ return ECONNRESET;
+ default:
+ bytes_read += rc;
+ }
+ } while (bytes_read < buf_size);
+
+ return APR_SUCCESS;
+}
+
+/* deal with signals
+ */
+static apr_status_t sock_write(int fd, const void *buf, size_t buf_size)
+{
+ int rc;
+
+ do {
+ rc = write(fd, buf, buf_size);
+ } while (rc < 0 && errno == EINTR);
+ if (rc < 0) {
+ return errno;
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t get_req(int fd, request_rec *r, char **argv0, char ***env,
+ cgid_req_t *req)
+{
+ int i;
+ char **environ;
+ core_request_config *temp_core;
+ void **rconf;
+ apr_status_t stat;
+
+ r->server = apr_pcalloc(r->pool, sizeof(server_rec));
+
+ /* read the request header */
+ stat = sock_read(fd, req, sizeof(*req));
+ if (stat != APR_SUCCESS) {
+ return stat;
+ }
+ r->server->loglevel = req->loglevel;
+ if (req->req_type == GETPID_REQ) {
+ /* no more data sent for this request */
+ return APR_SUCCESS;
+ }
+
+ /* handle module indexes and such */
+ rconf = (void **) apr_pcalloc(r->pool, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
+
+ temp_core = (core_request_config *)apr_palloc(r->pool, sizeof(core_module));
+ rconf[req->core_module_index] = (void *)temp_core;
+ r->request_config = (ap_conf_vector_t *)rconf;
+ ap_set_module_config(r->request_config, &cgid_module, (void *)&req->ugid);
+
+ /* Read the filename, argv0, uri, and args */
+ r->filename = apr_pcalloc(r->pool, req->filename_len + 1);
+ *argv0 = apr_pcalloc(r->pool, req->argv0_len + 1);
+ r->uri = apr_pcalloc(r->pool, req->uri_len + 1);
+ if ((stat = sock_read(fd, r->filename, req->filename_len)) != APR_SUCCESS ||
+ (stat = sock_read(fd, *argv0, req->argv0_len)) != APR_SUCCESS ||
+ (stat = sock_read(fd, r->uri, req->uri_len)) != APR_SUCCESS) {
+ return stat;
+ }
+
+ r->args = apr_pcalloc(r->pool, req->args_len + 1); /* empty string if no args */
+ if (req->args_len) {
+ if ((stat = sock_read(fd, r->args, req->args_len)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+
+ /* read the environment variables */
+ environ = apr_pcalloc(r->pool, (req->env_count + 2) *sizeof(char *));
+ for (i = 0; i < req->env_count; i++) {
+ apr_size_t curlen;
+
+ if ((stat = sock_read(fd, &curlen, sizeof(curlen))) != APR_SUCCESS) {
+ return stat;
+ }
+ environ[i] = apr_pcalloc(r->pool, curlen + 1);
+ if ((stat = sock_read(fd, environ[i], curlen)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+ *env = environ;
+
+#if 0
+#ifdef RLIMIT_CPU
+ sock_read(fd, &j, sizeof(int));
+ if (j) {
+ temp_core->limit_cpu = (struct rlimit *)apr_palloc (sizeof(struct rlimit));
+ sock_read(fd, temp_core->limit_cpu, sizeof(struct rlimit));
+ }
+ else {
+ temp_core->limit_cpu = NULL;
+ }
+#endif
+
+#if defined (RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+ sock_read(fd, &j, sizeof(int));
+ if (j) {
+ temp_core->limit_mem = (struct rlimit *)apr_palloc(r->pool, sizeof(struct rlimit));
+ sock_read(fd, temp_core->limit_mem, sizeof(struct rlimit));
+ }
+ else {
+ temp_core->limit_mem = NULL;
+ }
+#endif
+
+#ifdef RLIMIT_NPROC
+ sock_read(fd, &j, sizeof(int));
+ if (j) {
+ temp_core->limit_nproc = (struct rlimit *)apr_palloc(r->pool, sizeof(struct rlimit));
+ sock_read(fd, temp_core->limit_nproc, sizeof(struct rlimit));
+ }
+ else {
+ temp_core->limit_nproc = NULL;
+ }
+#endif
+#endif
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t send_req(int fd, request_rec *r, char *argv0, char **env,
+ int req_type)
+{
+ int i;
+ cgid_req_t req = {0};
+ apr_status_t stat;
+ ap_unix_identity_t * ugid = ap_run_get_suexec_identity(r);
+
+ if (ugid == NULL) {
+ req.ugid = empty_ugid;
+ } else {
+ memcpy(&req.ugid, ugid, sizeof(ap_unix_identity_t));
+ }
+
+ req.req_type = req_type;
+ req.conn_id = r->connection->id;
+ req.core_module_index = core_module.module_index;
+ for (req.env_count = 0; env[req.env_count]; req.env_count++) {
+ continue;
+ }
+ req.filename_len = strlen(r->filename);
+ req.argv0_len = strlen(argv0);
+ req.uri_len = strlen(r->uri);
+ req.args_len = r->args ? strlen(r->args) : 0;
+ req.loglevel = r->server->loglevel;
+
+ /* Write the request header */
+ if ((stat = sock_write(fd, &req, sizeof(req))) != APR_SUCCESS) {
+ return stat;
+ }
+
+ /* Write filename, argv0, uri, and args */
+ if ((stat = sock_write(fd, r->filename, req.filename_len)) != APR_SUCCESS ||
+ (stat = sock_write(fd, argv0, req.argv0_len)) != APR_SUCCESS ||
+ (stat = sock_write(fd, r->uri, req.uri_len)) != APR_SUCCESS) {
+ return stat;
+ }
+ if (req.args_len) {
+ if ((stat = sock_write(fd, r->args, req.args_len)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+
+ /* write the environment variables */
+ for (i = 0; i < req.env_count; i++) {
+ apr_size_t curlen = strlen(env[i]);
+
+ if ((stat = sock_write(fd, &curlen, sizeof(curlen))) != APR_SUCCESS) {
+ return stat;
+ }
+
+ if ((stat = sock_write(fd, env[i], curlen)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+
+#if 0
+#ifdef RLIMIT_CPU
+ if (conf->limit_cpu) {
+ len = 1;
+ stat = sock_write(fd, &len, sizeof(int));
+ stat = sock_write(fd, conf->limit_cpu, sizeof(struct rlimit));
+ }
+ else {
+ len = 0;
+ stat = sock_write(fd, &len, sizeof(int));
+ }
+#endif
+
+#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
+ if (conf->limit_mem) {
+ len = 1;
+ stat = sock_write(fd, &len, sizeof(int));
+ stat = sock_write(fd, conf->limit_mem, sizeof(struct rlimit));
+ }
+ else {
+ len = 0;
+ stat = sock_write(fd, &len, sizeof(int));
+ }
+#endif
+
+#ifdef RLIMIT_NPROC
+ if (conf->limit_nproc) {
+ len = 1;
+ stat = sock_write(fd, &len, sizeof(int));
+ stat = sock_write(fd, conf->limit_nproc, sizeof(struct rlimit));
+ }
+ else {
+ len = 0;
+ stat = sock_write(fd, &len, sizeof(int));
+ }
+#endif
+#endif
+ return APR_SUCCESS;
+}
+
+static void daemon_signal_handler(int sig)
+{
+ if (sig == SIGHUP) {
+ ++daemon_should_exit;
+ }
+}
+
+static void cgid_child_errfn(apr_pool_t *pool, apr_status_t err,
+ const char *description)
+{
+ request_rec *r;
+ void *vr;
+
+ apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);
+ r = vr;
+
+ /* sure we got r, but don't call ap_log_rerror() because we don't
+ * have r->headers_in and possibly other storage referenced by
+ * ap_log_rerror()
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, err, r->server, "%s",
+#ifdef AP_UNSAFE_ERROR_LOG_UNESCAPED
+ description
+#else
+ ap_escape_logitem(pool, description)
+#endif
+ );
+}
+
+static int cgid_server(void *data)
+{
+ struct sockaddr_un unix_addr;
+ int sd, sd2, rc;
+ mode_t omask;
+ apr_socklen_t len;
+ apr_pool_t *ptrans;
+ server_rec *main_server = data;
+ cgid_server_conf *sconf = ap_get_module_config(main_server->module_config,
+ &cgid_module);
+ apr_hash_t *script_hash = apr_hash_make(pcgi);
+
+ apr_pool_create(&ptrans, pcgi);
+
+ apr_signal(SIGCHLD, SIG_IGN);
+ apr_signal(SIGHUP, daemon_signal_handler);
+
+ if (unlink(sconf->sockname) < 0 && errno != ENOENT) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
+ "Couldn't unlink unix domain socket %s",
+ sconf->sockname);
+ /* just a warning; don't bail out */
+ }
+
+ /* cgid should use its own suexec doer */
+ ap_hook_get_suexec_identity(cgid_suexec_id_doer, NULL, NULL,
+ APR_HOOK_REALLY_FIRST);
+ apr_hook_sort_all();
+
+ if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
+ "Couldn't create unix domain socket");
+ return errno;
+ }
+
+ memset(&unix_addr, 0, sizeof(unix_addr));
+ unix_addr.sun_family = AF_UNIX;
+ strcpy(unix_addr.sun_path, sconf->sockname);
+
+ omask = umask(0077); /* so that only Apache can use socket */
+ rc = bind(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr));
+ umask(omask); /* can't fail, so can't clobber errno */
+ if (rc < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
+ "Couldn't bind unix domain socket %s",
+ sconf->sockname);
+ return errno;
+ }
+
+ if (listen(sd, DEFAULT_CGID_LISTENBACKLOG) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
+ "Couldn't listen on unix domain socket");
+ return errno;
+ }
+
+ if (!geteuid()) {
+ if (chown(sconf->sockname, unixd_config.user_id, -1) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
+ "Couldn't change owner of unix domain socket %s",
+ sconf->sockname);
+ return errno;
+ }
+ }
+
+ unixd_setup_child(); /* if running as root, switch to configured user/group */
+
+ while (!daemon_should_exit) {
+ int errfileno = STDERR_FILENO;
+ char *argv0;
+ char **env;
+ const char * const *argv;
+ apr_int32_t in_pipe;
+ apr_int32_t out_pipe;
+ apr_int32_t err_pipe;
+ apr_cmdtype_e cmd_type;
+ request_rec *r;
+ apr_procattr_t *procattr = NULL;
+ apr_proc_t *procnew = NULL;
+ apr_file_t *inout;
+ cgid_req_t cgid_req;
+ apr_status_t stat;
+
+ apr_pool_clear(ptrans);
+
+ len = sizeof(unix_addr);
+ sd2 = accept(sd, (struct sockaddr *)&unix_addr, &len);
+ if (sd2 < 0) {
+ if (errno != EINTR) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, errno,
+ (server_rec *)data,
+ "Error accepting on cgid socket");
+ }
+ continue;
+ }
+
+ r = apr_pcalloc(ptrans, sizeof(request_rec));
+ procnew = apr_pcalloc(ptrans, sizeof(*procnew));
+ r->pool = ptrans;
+ stat = get_req(sd2, r, &argv0, &env, &cgid_req);
+ if (stat != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, stat,
+ main_server,
+ "Error reading request on cgid socket");
+ close(sd2);
+ continue;
+ }
+
+ if (cgid_req.req_type == GETPID_REQ) {
+ pid_t pid;
+
+ pid = (pid_t)apr_hash_get(script_hash, &cgid_req.conn_id, sizeof(cgid_req.conn_id));
+ if (write(sd2, &pid, sizeof(pid)) != sizeof(pid)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0,
+ main_server,
+ "Error writing pid %" APR_PID_T_FMT " to handler", pid);
+ }
+ close(sd2);
+ continue;
+ }
+
+ apr_os_file_put(&r->server->error_log, &errfileno, 0, r->pool);
+ apr_os_file_put(&inout, &sd2, 0, r->pool);
+
+ if (cgid_req.req_type == SSI_REQ) {
+ in_pipe = APR_NO_PIPE;
+ out_pipe = APR_FULL_BLOCK;
+ err_pipe = APR_NO_PIPE;
+ cmd_type = APR_SHELLCMD;
+ }
+ else {
+ in_pipe = APR_CHILD_BLOCK;
+ out_pipe = APR_CHILD_BLOCK;
+ err_pipe = APR_CHILD_BLOCK;
+ cmd_type = APR_PROGRAM;
+ }
+
+ if (((rc = apr_procattr_create(&procattr, ptrans)) != APR_SUCCESS) ||
+ ((cgid_req.req_type == CGI_REQ) &&
+ (((rc = apr_procattr_io_set(procattr,
+ in_pipe,
+ out_pipe,
+ err_pipe)) != APR_SUCCESS) ||
+ /* XXX apr_procattr_child_*_set() is creating an unnecessary
+ * pipe between this process and the child being created...
+ * It is cleaned up with the temporary pool for this request.
+ */
+ ((rc = apr_procattr_child_err_set(procattr, r->server->error_log, NULL)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_child_in_set(procattr, inout, NULL)) != APR_SUCCESS))) ||
+ ((rc = apr_procattr_child_out_set(procattr, inout, NULL)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_dir_set(procattr,
+ ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
+ ((rc = apr_procattr_cmdtype_set(procattr, cmd_type)) != APR_SUCCESS) ||
+ ((rc = apr_procattr_child_errfn_set(procattr, cgid_child_errfn)) != APR_SUCCESS)) {
+ /* Something bad happened, tell the world.
+ * ap_log_rerror() won't work because the header table used by
+ * ap_log_rerror() hasn't been replicated in the phony r
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
+ "couldn't set child process attributes: %s", r->filename);
+ }
+ else {
+ apr_pool_userdata_set(r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ptrans);
+
+ argv = (const char * const *)create_argv(r->pool, NULL, NULL, NULL, argv0, r->args);
+
+ /* We want to close sd2 for the new CGI process too.
+ * If it is left open it'll make ap_pass_brigade() block
+ * waiting for EOF if CGI forked something running long.
+ * close(sd2) here should be okay, as CGI channel
+ * is already dup()ed by apr_procattr_child_{in,out}_set()
+ * above.
+ */
+ close(sd2);
+
+ if (memcmp(&empty_ugid, &cgid_req.ugid, sizeof(empty_ugid))) {
+ /* We have a valid identity, and can be sure that
+ * cgid_suexec_id_doer will return a valid ugid
+ */
+ rc = ap_os_create_privileged_process(r, procnew, argv0, argv,
+ (const char * const *)env,
+ procattr, ptrans);
+ } else {
+ rc = apr_proc_create(procnew, argv0, argv,
+ (const char * const *)env,
+ procattr, ptrans);
+ }
+
+ if (rc != APR_SUCCESS) {
+ /* Bad things happened. Everyone should have cleaned up.
+ * ap_log_rerror() won't work because the header table used by
+ * ap_log_rerror() hasn't been replicated in the phony r
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
+ "couldn't create child process: %d: %s", rc,
+ apr_filename_of_pathname(r->filename));
+ }
+ else {
+ /* We don't want to leak storage for the key, so only allocate
+ * a key if the key doesn't exist yet in the hash; there are
+ * only a limited number of possible keys (one for each
+ * possible thread in the server), so we can allocate a copy
+ * of the key the first time a thread has a cgid request.
+ * Note that apr_hash_set() only uses the storage passed in
+ * for the key if it is adding the key to the hash for the
+ * first time; new key storage isn't needed for replacing the
+ * existing value of a key.
+ */
+ void *key;
+
+ if (apr_hash_get(script_hash, &cgid_req.conn_id, sizeof(cgid_req.conn_id))) {
+ key = &cgid_req.conn_id;
+ }
+ else {
+ key = apr_pcalloc(pcgi, sizeof(cgid_req.conn_id));
+ memcpy(key, &cgid_req.conn_id, sizeof(cgid_req.conn_id));
+ }
+ apr_hash_set(script_hash, key, sizeof(cgid_req.conn_id),
+ (void *)procnew->pid);
+ }
+ }
+ }
+ return -1;
+}
+
+static int cgid_start(apr_pool_t *p, server_rec *main_server,
+ apr_proc_t *procnew)
+{
+ daemon_should_exit = 0; /* clear setting from previous generation */
+ if ((daemon_pid = fork()) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
+ "mod_cgid: Couldn't spawn cgid daemon process");
+ return DECLINED;
+ }
+ else if (daemon_pid == 0) {
+ if (pcgi == NULL) {
+ apr_pool_create(&pcgi, p);
+ }
+ cgid_server(main_server);
+ exit(-1);
+ }
+ procnew->pid = daemon_pid;
+ procnew->err = procnew->in = procnew->out = NULL;
+ apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
+#if APR_HAS_OTHER_CHILD
+ apr_proc_other_child_register(procnew, cgid_maint, procnew, NULL, p);
+#endif
+ return OK;
+}
+
+static int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
+ server_rec *main_server)
+{
+ apr_proc_t *procnew = NULL;
+ int first_time = 0;
+ const char *userdata_key = "cgid_init";
+ module **m;
+ int ret = OK;
+
+ root_server = main_server;
+ root_pool = p;
+
+ apr_pool_userdata_get((void **)&procnew, userdata_key, main_server->process->pool);
+ if (!procnew) {
+ first_time = 1;
+ procnew = apr_pcalloc(main_server->process->pool, sizeof(*procnew));
+ procnew->pid = -1;
+ procnew->err = procnew->in = procnew->out = NULL;
+ apr_pool_userdata_set((const void *)procnew, userdata_key,
+ apr_pool_cleanup_null, main_server->process->pool);
+ }
+
+ if (!first_time) {
+ total_modules = 0;
+ for (m = ap_preloaded_modules; *m != NULL; m++)
+ total_modules++;
+
+ ret = cgid_start(p, main_server, procnew);
+ if (ret != OK ) {
+ return ret;
+ }
+ cgid_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
+ cgid_pfn_gtv = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);
+ cgid_pfn_ps = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);
+
+ if ((cgid_pfn_reg_with_ssi) && (cgid_pfn_gtv) && (cgid_pfn_ps)) {
+ /* Required by mod_include filter. This is how mod_cgid registers
+ * with mod_include to provide processing of the exec directive.
+ */
+ cgid_pfn_reg_with_ssi("exec", handle_exec);
+ }
+ }
+ return ret;
+}
+
+static void *create_cgid_config(apr_pool_t *p, server_rec *s)
+{
+ cgid_server_conf *c =
+ (cgid_server_conf *) apr_pcalloc(p, sizeof(cgid_server_conf));
+
+ c->logname = NULL;
+ c->logbytes = DEFAULT_LOGBYTES;
+ c->bufbytes = DEFAULT_BUFBYTES;
+ c->sockname = ap_server_root_relative(p, DEFAULT_SOCKET);
+ return c;
+}
+
+static void *merge_cgid_config(apr_pool_t *p, void *basev, void *overridesv)
+{
+ cgid_server_conf *base = (cgid_server_conf *) basev, *overrides = (cgid_server_conf *) overridesv;
+
+ return overrides->logname ? overrides : base;
+}
+
+static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ server_rec *s = cmd->server;
+ cgid_server_conf *conf = ap_get_module_config(s->module_config,
+ &cgid_module);
+
+ conf->logname = ap_server_root_relative(cmd->pool, arg);
+
+ if (!conf->logname) {
+ return apr_pstrcat(cmd->pool, "Invalid ScriptLog path ",
+ arg, NULL);
+ }
+ return NULL;
+}
+
+static const char *set_scriptlog_length(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ server_rec *s = cmd->server;
+ cgid_server_conf *conf = ap_get_module_config(s->module_config,
+ &cgid_module);
+
+ conf->logbytes = atol(arg);
+ return NULL;
+}
+
+static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ server_rec *s = cmd->server;
+ cgid_server_conf *conf = ap_get_module_config(s->module_config,
+ &cgid_module);
+
+ conf->bufbytes = atoi(arg);
+ return NULL;
+}
+
+static const char *set_script_socket(cmd_parms *cmd, void *dummy, const char *arg)
+{
+ server_rec *s = cmd->server;
+ cgid_server_conf *conf = ap_get_module_config(s->module_config,
+ &cgid_module);
+
+ conf->sockname = ap_server_root_relative(cmd->pool, arg);
+
+ if (!conf->sockname) {
+ return apr_pstrcat(cmd->pool, "Invalid Scriptsock path ",
+ arg, NULL);
+ }
+
+ return NULL;
+}
+
+static const command_rec cgid_cmds[] =
+{
+ AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
+ "the name of a log for script debugging info"),
+ AP_INIT_TAKE1("ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF,
+ "the maximum length (in bytes) of the script debug log"),
+ AP_INIT_TAKE1("ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF,
+ "the maximum size (in bytes) to record of a POST request"),
+ AP_INIT_TAKE1("Scriptsock", set_script_socket, NULL, RSRC_CONF,
+ "the name of the socket to use for communication with "
+ "the cgi daemon."),
+ {NULL}
+};
+
+static int log_scripterror(request_rec *r, cgid_server_conf * conf, int ret,
+ apr_status_t rv, char *error)
+{
+ apr_file_t *f = NULL;
+ struct stat finfo;
+ char time_str[APR_CTIME_LEN];
+ int log_flags = rv ? APLOG_ERR : APLOG_ERR;
+
+ ap_log_rerror(APLOG_MARK, log_flags, rv, r,
+ "%s: %s", error, r->filename);
+
+ /* XXX Very expensive mainline case! Open, then getfileinfo! */
+ if (!conf->logname ||
+ ((stat(conf->logname, &finfo) == 0)
+ && (finfo.st_size > conf->logbytes)) ||
+ (apr_file_open(&f, conf->logname,
+ APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
+ return ret;
+ }
+
+ /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-bin/printenv HTTP/1.0" */
+ apr_ctime(time_str, apr_time_now());
+ apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
+ r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+ /* "%% 500 /usr/local/apache/cgid-bin */
+ apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
+
+ apr_file_printf(f, "%%error\n%s\n", error);
+
+ apr_file_close(f);
+ return ret;
+}
+
+static int log_script(request_rec *r, cgid_server_conf * conf, int ret,
+ char *dbuf, const char *sbuf, apr_bucket_brigade *bb,
+ apr_file_t *script_err)
+{
+ const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
+ const apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
+ char argsbuffer[HUGE_STRING_LEN];
+ apr_file_t *f = NULL;
+ apr_bucket *e;
+ const char *buf;
+ apr_size_t len;
+ apr_status_t rv;
+ int first;
+ int i;
+ struct stat finfo;
+ char time_str[APR_CTIME_LEN];
+
+ /* XXX Very expensive mainline case! Open, then getfileinfo! */
+ if (!conf->logname ||
+ ((stat(conf->logname, &finfo) == 0)
+ && (finfo.st_size > conf->logbytes)) ||
+ (apr_file_open(&f, conf->logname,
+ APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
+ /* Soak up script output */
+ discard_script_output(bb);
+ if (script_err) {
+ while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+ script_err) == APR_SUCCESS)
+ continue;
+ }
+ return ret;
+ }
+
+ /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-bin/printenv HTTP/1.0" */
+ apr_ctime(time_str, apr_time_now());
+ apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
+ r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+ /* "%% 500 /usr/local/apache/cgid-bin" */
+ apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
+
+ apr_file_puts("%request\n", f);
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (!hdrs[i].key)
+ continue;
+ apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+ }
+ if ((r->method_number == M_POST || r->method_number == M_PUT)
+ && *dbuf) {
+ apr_file_printf(f, "\n%s\n", dbuf);
+ }
+
+ apr_file_puts("%response\n", f);
+ hdrs_arr = apr_table_elts(r->err_headers_out);
+ hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
+
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
+ if (!hdrs[i].key)
+ continue;
+ apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+ }
+
+ if (sbuf && *sbuf)
+ apr_file_printf(f, "%s\n", sbuf);
+
+ first = 1;
+ APR_BRIGADE_FOREACH(e, bb) {
+ if (APR_BUCKET_IS_EOS(e)) {
+ break;
+ }
+ rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
+ if (!APR_STATUS_IS_SUCCESS(rv) || (len == 0)) {
+ break;
+ }
+ if (first) {
+ apr_file_puts("%stdout\n", f);
+ first = 0;
+ }
+ apr_file_write(f, buf, &len);
+ apr_file_puts("\n", f);
+ }
+
+ if (script_err) {
+ if (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+ script_err) == APR_SUCCESS) {
+ apr_file_puts("%stderr\n", f);
+ apr_file_puts(argsbuffer, f);
+ while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+ script_err) == APR_SUCCESS)
+ apr_file_puts(argsbuffer, f);
+ apr_file_puts("\n", f);
+ }
+ }
+
+ if (script_err) {
+ apr_file_close(script_err);
+ }
+
+ apr_file_close(f);
+ return ret;
+}
+
+static apr_status_t close_unix_socket(void *thefd)
+{
+ int fd = (int)thefd;
+
+ return close(fd);
+}
+
+static int connect_to_daemon(int *sdptr, request_rec *r,
+ cgid_server_conf *conf)
+{
+ struct sockaddr_un unix_addr;
+ int sd;
+ int connect_tries;
+ apr_interval_time_t sliding_timer;
+
+ memset(&unix_addr, 0, sizeof(unix_addr));
+ unix_addr.sun_family = AF_UNIX;
+ strcpy(unix_addr.sun_path, conf->sockname);
+
+ connect_tries = 0;
+ sliding_timer = 100000; /* 100 milliseconds */
+ while (1) {
+ ++connect_tries;
+ if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, errno,
+ "unable to create socket to cgi daemon");
+ }
+ if (connect(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) {
+ if (errno == ECONNREFUSED && connect_tries < DEFAULT_CONNECT_ATTEMPTS) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, errno, r,
+ "connect #%d to cgi daemon failed, sleeping before retry",
+ connect_tries);
+ close(sd);
+ apr_sleep(sliding_timer);
+ if (sliding_timer < apr_time_from_sec(2)) {
+ sliding_timer *= 2;
+ }
+ }
+ else {
+ close(sd);
+ return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno,
+ "unable to connect to cgi daemon after multiple tries");
+ }
+ }
+ else {
+ apr_pool_cleanup_register(r->pool, (void *)sd, close_unix_socket,
+ apr_pool_cleanup_null);
+ break; /* we got connected! */
+ }
+ /* gotta try again, but make sure the cgid daemon is still around */
+ if (kill(daemon_pid, 0) != 0) {
+ return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno,
+ "cgid daemon is gone; is Apache terminating?");
+ }
+ }
+ *sdptr = sd;
+ return OK;
+}
+
+static void discard_script_output(apr_bucket_brigade *bb)
+{
+ apr_bucket *e;
+ const char *buf;
+ apr_size_t len;
+ apr_status_t rv;
+ APR_BRIGADE_FOREACH(e, bb) {
+ if (APR_BUCKET_IS_EOS(e)) {
+ break;
+ }
+ rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
+ if (!APR_STATUS_IS_SUCCESS(rv)) {
+ break;
+ }
+ }
+}
+
+/****************************************************************
+ *
+ * Actual cgid handling...
+ */
+
+struct cleanup_script_info {
+ request_rec *r;
+ unsigned long conn_id;
+ cgid_server_conf *conf;
+};
+
+static apr_status_t dead_yet(pid_t pid, apr_interval_time_t max_wait)
+{
+ apr_interval_time_t interval = 10000; /* 10 ms */
+ apr_interval_time_t total = 0;
+
+ do {
+#ifdef _AIX
+ /* On AIX, for processes like mod_cgid's script children where
+ * SIGCHLD is ignored, kill(pid,0) returns success for up to
+ * one second after the script child exits, based on when a
+ * daemon runs to clean up unnecessary process table entries.
+ * getpgid() can report the proper info (-1/ESRCH) immediately.
+ */
+ if (getpgid(pid) < 0) {
+#else
+ if (kill(pid, 0) < 0) {
+#endif
+ return APR_SUCCESS;
+ }
+ apr_sleep(interval);
+ total = total + interval;
+ if (interval < 500000) {
+ interval *= 2;
+ }
+ } while (total < max_wait);
+ return APR_EGENERAL;
+}
+
+static apr_status_t cleanup_nonchild_process(request_rec *r, pid_t pid)
+{
+ kill(pid, SIGTERM); /* in case it isn't dead yet */
+ if (dead_yet(pid, apr_time_from_sec(3)) == APR_SUCCESS) {
+ return APR_SUCCESS;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "CGI process %" APR_PID_T_FMT " didn't exit, sending SIGKILL",
+ pid);
+ kill(pid, SIGKILL);
+ if (dead_yet(pid, apr_time_from_sec(3)) == APR_SUCCESS) {
+ return APR_SUCCESS;
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "CGI process %" APR_PID_T_FMT " didn't exit, sending SIGKILL again",
+ pid);
+ kill(pid, SIGKILL);
+
+ return APR_EGENERAL;
+}
+
+static apr_status_t cleanup_script(void *vptr)
+{
+ struct cleanup_script_info *info = vptr;
+ int sd;
+ int rc;
+ cgid_req_t req = {0};
+ pid_t pid;
+ apr_status_t stat;
+
+ rc = connect_to_daemon(&sd, info->r, info->conf);
+ if (rc != OK) {
+ return APR_EGENERAL;
+ }
+
+ /* we got a socket, and there is already a cleanup registered for it */
+
+ req.req_type = GETPID_REQ;
+ req.conn_id = info->r->connection->id;
+
+ stat = sock_write(sd, &req, sizeof(req));
+ if (stat != APR_SUCCESS) {
+ return stat;
+ }
+
+ /* wait for pid of script */
+ stat = sock_read(sd, &pid, sizeof(pid));
+ if (stat != APR_SUCCESS) {
+ return stat;
+ }
+
+ if (pid == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, info->r,
+ "daemon couldn't find CGI process for connection %lu",
+ info->conn_id);
+ return APR_EGENERAL;
+ }
+ return cleanup_nonchild_process(info->r, pid);
+}
+
+static int cgid_handler(request_rec *r)
+{
+ conn_rec *c = r->connection;
+ int retval, nph, dbpos = 0;
+ char *argv0, *dbuf = NULL;
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ cgid_server_conf *conf;
+ int is_included;
+ int seen_eos, child_stopped_reading;
+ int sd;
+ char **env;
+ apr_file_t *tempsock;
+ struct cleanup_script_info *info;
+ apr_status_t rv;
+
+ if (strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))
+ return DECLINED;
+
+ conf = ap_get_module_config(r->server->module_config, &cgid_module);
+ is_included = !strcmp(r->protocol, "INCLUDED");
+
+ if ((argv0 = strrchr(r->filename, '/')) != NULL)
+ argv0++;
+ else
+ argv0 = r->filename;
+
+ nph = !(strncmp(argv0, "nph-", 4));
+
+ argv0 = r->filename;
+
+ if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "Options ExecCGI is off in this directory");
+ if (nph && is_included)
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "attempt to include NPH CGI script");
+
+#if defined(OS2) || defined(WIN32)
+#error mod_cgid does not work on this platform. If you teach it to, look
+#error at mod_cgi.c for required code in this path.
+#else
+ if (r->finfo.filetype == 0)
+ return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,
+ "script not found or unable to stat");
+#endif
+ if (r->finfo.filetype == APR_DIR)
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "attempt to invoke directory as script");
+
+ if ((r->used_path_info == AP_REQ_REJECT_PATH_INFO) &&
+ r->path_info && *r->path_info)
+ {
+ /* default to accept */
+ return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,
+ "AcceptPathInfo off disallows user's path");
+ }
+/*
+ if (!ap_suexec_enabled) {
+ if (!ap_can_exec(&r->finfo))
+ return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
+ "file permissions deny server execution");
+ }
+*/
+ ap_add_common_vars(r);
+ ap_add_cgi_vars(r);
+ env = ap_create_environment(r->pool, r->subprocess_env);
+
+ if ((retval = connect_to_daemon(&sd, r, conf)) != OK) {
+ return retval;
+ }
+
+ rv = send_req(sd, r, argv0, env, CGI_REQ);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "write to cgi daemon process");
+ }
+
+ info = apr_palloc(r->pool, sizeof(struct cleanup_script_info));
+ info->r = r;
+ info->conn_id = r->connection->id;
+ info->conf = conf;
+ apr_pool_cleanup_register(r->pool, info,
+ cleanup_script,
+ apr_pool_cleanup_null);
+ /* We are putting the socket discriptor into an apr_file_t so that we can
+ * use a pipe bucket to send the data to the client. APR will create
+ * a cleanup for the apr_file_t which will close the socket, so we'll
+ * get rid of the cleanup we registered when we created the socket.
+ */
+
+ apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
+ apr_pool_cleanup_kill(r->pool, (void *)sd, close_unix_socket);
+
+ if ((argv0 = strrchr(r->filename, '/')) != NULL)
+ argv0++;
+ else
+ argv0 = r->filename;
+
+ /* Transfer any put/post args, CERN style...
+ * Note that we already ignore SIGPIPE in the core server.
+ */
+ bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ seen_eos = 0;
+ child_stopped_reading = 0;
+ if (conf->logname) {
+ dbuf = apr_palloc(r->pool, conf->bufbytes + 1);
+ dbpos = 0;
+ }
+ do {
+ apr_bucket *bucket;
+
+ rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
+ APR_BLOCK_READ, HUGE_STRING_LEN);
+
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "Error reading request entity data");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ APR_BRIGADE_FOREACH(bucket, bb) {
+ const char *data;
+ apr_size_t len;
+
+ if (APR_BUCKET_IS_EOS(bucket)) {
+ seen_eos = 1;
+ break;
+ }
+
+ /* We can't do much with this. */
+ if (APR_BUCKET_IS_FLUSH(bucket)) {
+ continue;
+ }
+
+ /* If the child stopped, we still must read to EOS. */
+ if (child_stopped_reading) {
+ continue;
+ }
+
+ /* read */
+ apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
+
+ if (conf->logname && dbpos < conf->bufbytes) {
+ int cursize;
+
+ if ((dbpos + len) > conf->bufbytes) {
+ cursize = conf->bufbytes - dbpos;
+ }
+ else {
+ cursize = len;
+ }
+ memcpy(dbuf + dbpos, data, cursize);
+ dbpos += cursize;
+ }
+
+ /* Keep writing data to the child until done or too much time
+ * elapses with no progress or an error occurs.
+ */
+ rv = apr_file_write_full(tempsock, data, len, NULL);
+
+ if (rv != APR_SUCCESS) {
+ /* silly script stopped reading, soak up remaining message */
+ child_stopped_reading = 1;
+ }
+ }
+ apr_brigade_cleanup(bb);
+ }
+ while (!seen_eos);
+
+ if (conf->logname) {
+ dbuf[dbpos] = '\0';
+ }
+
+ /* we're done writing, or maybe we didn't write at all;
+ * force EOF on child's stdin so that the cgi detects end (or
+ * absence) of data
+ */
+ shutdown(sd, 1);
+
+ /* Handle script return... */
+ if (!nph) {
+ const char *location;
+ char sbuf[MAX_STRING_LEN];
+ int ret;
+
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+ b = apr_bucket_pipe_create(tempsock, c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+
+ if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) {
+ return log_script(r, conf, ret, dbuf, sbuf, bb, NULL);
+ }
+
+ location = apr_table_get(r->headers_out, "Location");
+
+ if (location && location[0] == '/' && r->status == 200) {
+
+ /* Soak up all the script output */
+ discard_script_output(bb);
+ apr_brigade_destroy(bb);
+ /* This redirect needs to be a GET no matter what the original
+ * method was.
+ */
+ r->method = apr_pstrdup(r->pool, "GET");
+ r->method_number = M_GET;
+
+ /* We already read the message body (if any), so don't allow
+ * the redirected request to think it has one. We can ignore
+ * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
+ */
+ apr_table_unset(r->headers_in, "Content-Length");
+
+ ap_internal_redirect_handler(location, r);
+ return OK;
+ }
+ else if (location && r->status == 200) {
+ /* XX Note that if a script wants to produce its own Redirect
+ * body, it now has to explicitly *say* "Status: 302"
+ */
+ discard_script_output(bb);
+ apr_brigade_destroy(bb);
+ return HTTP_MOVED_TEMPORARILY;
+ }
+
+ ap_pass_brigade(r->output_filters, bb);
+ }
+
+ if (nph) {
+ struct ap_filter_t *cur;
+
+ /* get rid of all filters up through protocol... since we
+ * haven't parsed off the headers, there is no way they can
+ * work
+ */
+
+ cur = r->proto_output_filters;
+ while (cur && cur->frec->ftype < AP_FTYPE_CONNECTION) {
+ cur = cur->next;
+ }
+ r->output_filters = r->proto_output_filters = cur;
+
+ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+ b = apr_bucket_pipe_create(tempsock, c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ b = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+ ap_pass_brigade(r->output_filters, bb);
+ }
+
+ return OK; /* NOT r->status, even if it has changed. */
+}
+
+
+
+
+/*============================================================================
+ *============================================================================
+ * This is the beginning of the cgi filter code moved from mod_include. This
+ * is the code required to handle the "exec" SSI directive.
+ *============================================================================
+ *============================================================================*/
+static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
+ apr_bucket *head_ptr, apr_bucket **inserted_head)
+{
+ request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
+ int rr_status;
+ apr_bucket *tmp_buck, *tmp2_buck;
+
+ if (rr->status != HTTP_OK) {
+ ap_destroy_sub_req(rr);
+ return -1;
+ }
+
+ /* No hardwired path info or query allowed */
+
+ if ((rr->path_info && rr->path_info[0]) || rr->args) {
+ ap_destroy_sub_req(rr);
+ return -1;
+ }
+ if (rr->finfo.filetype != APR_REG) {
+ ap_destroy_sub_req(rr);
+ return -1;
+ }
+
+ /* Script gets parameters of the *document*, for back compatibility */
+
+ rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */
+ rr->args = r->args;
+
+ /* Force sub_req to be treated as a CGI request, even if ordinary
+ * typing rules would have called it something else.
+ */
+ ap_set_content_type(rr, CGI_MAGIC_TYPE);
+
+ /* Run it. */
+
+ rr_status = ap_run_sub_req(rr);
+ if (ap_is_HTTP_REDIRECT(rr_status)) {
+ apr_size_t len_loc;
+ const char *location = apr_table_get(rr->headers_out, "Location");
+ conn_rec *c = r->connection;
+
+ location = ap_escape_html(rr->pool, location);
+ len_loc = strlen(location);
+
+ /* XXX: if most of this stuff is going to get copied anyway,
+ * it'd be more efficient to pstrcat it into a single pool buffer
+ * and a single pool bucket */
+
+ tmp_buck = apr_bucket_immortal_create("<A HREF=\"",
+ sizeof("<A HREF=\"") - 1,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
+ tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+ tmp2_buck = apr_bucket_immortal_create("\">", sizeof("\">") - 1,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+ tmp2_buck = apr_bucket_heap_create(location, len_loc, NULL,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+ tmp2_buck = apr_bucket_immortal_create("</A>", sizeof("</A>") - 1,
+ c->bucket_alloc);
+ APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
+
+ if (*inserted_head == NULL) {
+ *inserted_head = tmp_buck;
+ }
+ }
+
+ ap_destroy_sub_req(rr);
+
+ return 0;
+}
+
+
+/* This is the special environment used for running the "exec cmd="
+ * variety of SSI directives.
+ */
+static void add_ssi_vars(request_rec *r, ap_filter_t *next)
+{
+ apr_table_t *e = r->subprocess_env;
+
+ if (r->path_info && r->path_info[0] != '\0') {
+ request_rec *pa_req;
+
+ apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
+
+ pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, NULL);
+ if (pa_req->filename) {
+ apr_table_setn(e, "PATH_TRANSLATED",
+ apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL));
+ }
+ ap_destroy_sub_req(pa_req);
+ }
+
+ if (r->args) {
+ char *arg_copy = apr_pstrdup(r->pool, r->args);
+
+ apr_table_setn(e, "QUERY_STRING", r->args);
+ ap_unescape_url(arg_copy);
+ apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy));
+ }
+}
+
+static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *command,
+ request_rec *r, ap_filter_t *f)
+{
+ char **env;
+ int sd;
+ apr_status_t rc = APR_SUCCESS;
+ int retval;
+ apr_bucket_brigade *bcgi;
+ apr_bucket *b;
+ apr_file_t *tempsock = NULL;
+ cgid_server_conf *conf = ap_get_module_config(r->server->module_config,
+ &cgid_module);
+ struct cleanup_script_info *info;
+
+ add_ssi_vars(r, f->next);
+ env = ap_create_environment(r->pool, r->subprocess_env);
+
+ if ((retval = connect_to_daemon(&sd, r, conf)) != OK) {
+ return retval;
+ }
+
+ SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next, rc);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
+
+ send_req(sd, r, command, env, SSI_REQ);
+
+ info = apr_palloc(r->pool, sizeof(struct cleanup_script_info));
+ info->r = r;
+ info->conn_id = r->connection->id;
+ info->conf = conf;
+ /* for this type of request, the script is invoked through an
+ * intermediate shell process... cleanup_script is only able
+ * to knock out the shell process, not the actual script
+ */
+ apr_pool_cleanup_register(r->pool, info,
+ cleanup_script,
+ apr_pool_cleanup_null);
+ /* We are putting the socket discriptor into an apr_file_t so that we can
+ * use a pipe bucket to send the data to the client. APR will create
+ * a cleanup for the apr_file_t which will close the socket, so we'll
+ * get rid of the cleanup we registered when we created the socket.
+ */
+ apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
+ apr_pool_cleanup_kill(r->pool, (void *)sd, close_unix_socket);
+
+ bcgi = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ b = apr_bucket_pipe_create(tempsock, r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bcgi, b);
+ ap_pass_brigade(f->next, bcgi);
+
+ return 0;
+}
+
+static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
+ ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
+{
+ char *tag = NULL;
+ char *tag_val = NULL;
+ char *file = r->filename;
+ apr_bucket *tmp_buck;
+ char parsed_string[MAX_STRING_LEN];
+
+ *inserted_head = NULL;
+ if (ctx->flags & FLAG_PRINTING) {
+ if (ctx->flags & FLAG_NO_EXEC) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "exec used but not allowed in %s", r->filename);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
+ }
+ else {
+ while (1) {
+ cgid_pfn_gtv(ctx, &tag, &tag_val, 1);
+ if (tag_val == NULL) {
+ if (tag == NULL) {
+ return (0);
+ }
+ else {
+ return 1;
+ }
+ }
+ if (!strcmp(tag, "cmd")) {
+ cgid_pfn_ps(r, ctx, tag_val, parsed_string, sizeof(parsed_string), 1);
+ if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "execution failure for parameter \"%s\" "
+ "to tag exec in file %s", tag, r->filename);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
+ }
+ /* just in case some stooge changed directories */
+ }
+ else if (!strcmp(tag, "cgi")) {
+ apr_status_t retval = APR_SUCCESS;
+
+ cgid_pfn_ps(r, ctx, tag_val, parsed_string, sizeof(parsed_string), 0);
+ SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next, retval);
+ if (retval != APR_SUCCESS) {
+ return retval;
+ }
+
+ if (include_cgi(parsed_string, r, f->next, head_ptr, inserted_head) == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "invalid CGI ref \"%s\" in %s", tag_val, file);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "unknown parameter \"%s\" to tag exec in %s", tag, file);
+ CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
+ }
+ }
+ }
+ }
+ return 0;
+}
+/*============================================================================
+ *============================================================================
+ * This is the end of the cgi filter code moved from mod_include.
+ *============================================================================
+ *============================================================================*/
+
+
+static void register_hook(apr_pool_t *p)
+{
+ static const char * const aszPre[] = { "mod_include.c", NULL };
+
+ ap_hook_post_config(cgid_init, aszPre, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(cgid_handler, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA cgid_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ create_cgid_config, /* server config */
+ merge_cgid_config, /* merge server config */
+ cgid_cmds, /* command table */
+ register_hook /* register_handlers */
+};
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.exp b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.exp
new file mode 100644
index 00000000..5f10d486
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.exp
@@ -0,0 +1 @@
+cgid_module
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.la b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.la
new file mode 100644
index 00000000..7528f2d9
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.la
@@ -0,0 +1,35 @@
+# mod_cgid.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_cgid.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_cgid.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.lo b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.lo
new file mode 100644
index 00000000..3d819a78
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.lo
@@ -0,0 +1,12 @@
+# mod_cgid.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object='.libs/mod_cgid.o'
+
+# Name of the non-PIC object.
+non_pic_object='mod_cgid.o'
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.o b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.o
new file mode 100644
index 00000000..ffbaef81
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_info.c b/rubbos/app/httpd-2.0.64/modules/generators/mod_info.c
new file mode 100644
index 00000000..eb728442
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_info.c
@@ -0,0 +1,533 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Info Module. Display configuration information for the server and
+ * all included modules.
+ *
+ * <Location /server-info>
+ * SetHandler server-info
+ * </Location>
+ *
+ * GET /server-info - Returns full configuration page for server and all modules
+ * GET /server-info?server - Returns server configuration only
+ * GET /server-info?module_name - Returns configuration for a single module
+ * GET /server-info?list - Returns quick list of included modules
+ *
+ * Rasmus Lerdorf <rasmus@vex.net>, May 1996
+ *
+ * 05.01.96 Initial Version
+ *
+ * Lou Langholtz <ldl@usi.utah.edu>, July 1997
+ *
+ * 07.11.97 Addition of the AddModuleInfo directive
+ *
+ * Ryan Morgan <rmorgan@covalent.net>
+ *
+ * 8.11.00 Port to Apache 2.0. Read configuation from the configuration
+ * tree rather than reparse the entire configuation file.
+ *
+ */
+
+#define CORE_PRIVATE
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_protocol.h"
+#include "http_request.h"
+#include "util_script.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "ap_mpm.h"
+
+typedef struct {
+ const char *name; /* matching module name */
+ const char *info; /* additional info */
+} info_entry;
+
+typedef struct {
+ apr_array_header_t *more_info;
+} info_svr_conf;
+
+module AP_MODULE_DECLARE_DATA info_module;
+
+static void *create_info_config(apr_pool_t *p, server_rec *s)
+{
+ info_svr_conf *conf = (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
+
+ conf->more_info = apr_array_make(p, 20, sizeof(info_entry));
+ return conf;
+}
+
+static void *merge_info_config(apr_pool_t *p, void *basev, void *overridesv)
+{
+ info_svr_conf *new = (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
+ info_svr_conf *base = (info_svr_conf *) basev;
+ info_svr_conf *overrides = (info_svr_conf *) overridesv;
+
+ new->more_info = apr_array_append(p, overrides->more_info, base->more_info);
+ return new;
+}
+
+static void mod_info_html_cmd_string(request_rec *r, const char *string,
+ int close)
+{
+ const char *s;
+
+ s = string;
+ /* keep space for \0 byte */
+ while (*s) {
+ if (*s == '<') {
+ if (close) {
+ ap_rputs("&lt;/", r);
+ } else {
+ ap_rputs("&lt;", r);
+ }
+ }
+ else if (*s == '>') {
+ ap_rputs("&gt;", r);
+ }
+ else if (*s == '&') {
+ ap_rputs("&amp;", r);
+ }
+ else if (*s == ' ') {
+ if (close) {
+ ap_rputs("&gt;", r);
+ break;
+ } else {
+ ap_rputc(*s, r);
+ }
+ } else {
+ ap_rputc(*s, r);
+ }
+ s++;
+ }
+}
+
+static void mod_info_module_cmds(request_rec * r, const command_rec * cmds,
+ ap_directive_t * conftree)
+{
+ const command_rec *cmd;
+ ap_directive_t *tmptree = conftree;
+ char htmlstring[MAX_STRING_LEN];
+ int block_start = 0;
+ int nest = 0;
+
+ while (tmptree != NULL) {
+ cmd = cmds;
+ while (cmd->name) {
+ if ((cmd->name[0] != '<') &&
+ (strcasecmp(cmd->name, tmptree->directive) == 0)) {
+ if (nest > block_start) {
+ block_start++;
+ apr_snprintf(htmlstring, sizeof(htmlstring), "%s %s",
+ tmptree->parent->directive,
+ tmptree->parent->args);
+ ap_rputs("<dd><tt>", r);
+ mod_info_html_cmd_string(r, htmlstring, 0);
+ ap_rputs("</tt></dd>\n", r);
+ }
+ if (nest == 2) {
+ ap_rprintf(r, "<dd><tt>&nbsp;&nbsp;&nbsp;&nbsp;%s "
+ "<i>%s</i></tt></dd>\n",
+ ap_escape_html(r->pool,tmptree->directive),
+ ap_escape_html(r->pool,tmptree->args));
+ } else if (nest == 1) {
+ ap_rprintf(r,
+ "<dd><tt>&nbsp;&nbsp;%s <i>%s</i></tt></dd>\n",
+ ap_escape_html(r->pool,tmptree->directive),
+ ap_escape_html(r->pool,tmptree->args));
+ } else {
+ ap_rputs("<dd><tt>", r);
+ mod_info_html_cmd_string(r, tmptree->directive, 0);
+ ap_rprintf(r, " <i>%s</i></tt></dd>\n",
+ ap_escape_html(r->pool,tmptree->args));
+ }
+ }
+ ++cmd;
+ }
+ if (tmptree->first_child != NULL) {
+ tmptree = tmptree->first_child;
+ nest++;
+ } else if (tmptree->next != NULL) {
+ tmptree = tmptree->next;
+ } else {
+ if (block_start) {
+ apr_snprintf(htmlstring, sizeof(htmlstring), "%s %s",
+ tmptree->parent->directive,
+ tmptree->parent->args);
+ ap_rputs("<dd><tt>", r);
+ mod_info_html_cmd_string(r, htmlstring, 1);
+ ap_rputs("</tt></dd>\n", r);
+ block_start--;
+ }
+ if (tmptree->parent) {
+ tmptree = tmptree->parent->next;
+ }
+ else {
+ tmptree = NULL;
+ }
+ nest--;
+ }
+
+ }
+}
+
+typedef struct { /*XXX: should get something from apr_hooks.h instead */
+ void (*pFunc)(void); /* just to get the right size */
+ const char *szName;
+ const char * const *aszPredecessors;
+ const char * const *aszSuccessors;
+ int nOrder;
+} hook_struct_t;
+
+/*
+ * hook_get_t is a pointer to a function that takes void as an argument and
+ * returns a pointer to an apr_array_header_t. The nasty WIN32 ifdef
+ * is required to account for the fact that the ap_hook* calls all use
+ * STDCALL calling convention.
+ */
+typedef apr_array_header_t * (
+#ifdef WIN32
+__stdcall
+#endif
+* hook_get_t)(void);
+
+typedef struct {
+ const char *name;
+ hook_get_t get;
+} hook_lookup_t;
+
+static hook_lookup_t request_hooks[] = {
+ {"Post-Read Request", ap_hook_get_post_read_request},
+ {"Header Parse", ap_hook_get_header_parser},
+ {"Translate Path", ap_hook_get_translate_name},
+ {"Check Access", ap_hook_get_access_checker},
+ {"Verify User ID", ap_hook_get_check_user_id},
+ {"Verify User Access", ap_hook_get_auth_checker},
+ {"Check Type", ap_hook_get_type_checker},
+ {"Fixups", ap_hook_get_fixups},
+ {"Logging", ap_hook_get_log_transaction},
+ {NULL},
+};
+
+static int module_find_hook(module *modp,
+ hook_get_t hook_get)
+{
+ int i;
+ apr_array_header_t *hooks = hook_get();
+ hook_struct_t *elts;
+
+ if (!hooks) {
+ return 0;
+ }
+
+ elts = (hook_struct_t *)hooks->elts;
+
+ for (i=0; i< hooks->nelts; i++) {
+ if (strcmp(elts[i].szName, modp->name) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void module_participate(request_rec *r,
+ module *modp,
+ hook_lookup_t *lookup,
+ int *comma)
+{
+ if (module_find_hook(modp, lookup->get)) {
+ if (*comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rvputs(r, "<tt>", lookup->name, "</tt>", NULL);
+ *comma = 1;
+ }
+}
+
+static void module_request_hook_participate(request_rec *r, module *modp)
+{
+ int i, comma=0;
+
+ ap_rputs("<dt><strong>Request Phase Participation:</strong>\n", r);
+
+ for (i=0; request_hooks[i].name; i++) {
+ module_participate(r, modp, &request_hooks[i], &comma);
+ }
+
+ if (!comma) {
+ ap_rputs("<tt> <em>none</em></tt>", r);
+ }
+ ap_rputs("</dt>\n", r);
+}
+
+static const char *find_more_info(server_rec *s, const char *module_name)
+{
+ int i;
+ info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
+ &info_module);
+ info_entry *entry = (info_entry *) conf->more_info->elts;
+
+ if (!module_name) {
+ return 0;
+ }
+ for (i = 0; i < conf->more_info->nelts; i++) {
+ if (!strcmp(module_name, entry->name)) {
+ return entry->info;
+ }
+ entry++;
+ }
+ return 0;
+}
+
+static int display_info(request_rec *r)
+{
+ module *modp = NULL;
+ const char *more_info;
+ const command_rec *cmd = NULL;
+#ifdef NEVERMORE
+ const handler_rec *hand = NULL;
+#endif
+ server_rec *serv = r->server;
+ int comma = 0;
+
+ if (strcmp(r->handler, "server-info"))
+ return DECLINED;
+
+ r->allowed |= (AP_METHOD_BIT << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+
+ ap_set_content_type(r, "text/html; charset=ISO-8859-1");
+
+ ap_rputs(DOCTYPE_HTML_3_2
+ "<html><head><title>Server Information</title></head>\n", r);
+ ap_rputs("<body><h1 align=\"center\">Apache Server Information</h1>\n", r);
+ if (!r->args || strcasecmp(r->args, "list")) {
+ if (!r->args) {
+ ap_rputs("<dl><dt><tt><a href=\"#server\">Server Settings</a>, ", r);
+ for (modp = ap_top_module; modp; modp = modp->next) {
+ ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name, modp->name);
+ if (modp->next) {
+ ap_rputs(", ", r);
+ }
+ }
+ ap_rputs("</tt></dt></dl><hr />", r);
+
+ }
+ if (!r->args || !strcasecmp(r->args, "server")) {
+ int max_daemons, forked, threaded;
+
+ ap_rprintf(r, "<dl><dt><a name=\"server\"><strong>Server Version:</strong> "
+ "<font size=\"+1\"><tt>%s</tt></font></a></dt>\n",
+ ap_get_server_version());
+ ap_rprintf(r, "<dt><strong>Server Built:</strong> "
+ "<font size=\"+1\"><tt>%s</tt></font></dt>\n",
+ ap_get_server_built());
+ ap_rprintf(r, "<dt><strong>API Version:</strong> "
+ "<tt>%d:%d</tt></dt>\n",
+ MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
+ ap_rprintf(r, "<dt><strong>Hostname/port:</strong> "
+ "<tt>%s:%u</tt></dt>\n",
+ ap_get_server_name(r), ap_get_server_port(r));
+ ap_rprintf(r, "<dt><strong>Timeouts:</strong> "
+ "<tt>connection: %d &nbsp;&nbsp; "
+ "keep-alive: %d</tt></dt>",
+ (int)(apr_time_sec(serv->timeout)),
+ (int)(apr_time_sec(serv->timeout)));
+ ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons);
+ ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded);
+ ap_mpm_query(AP_MPMQ_IS_FORKED, &forked);
+ ap_rprintf(r, "<dt><strong>MPM Name:</strong> <tt>%s</tt></dt>\n", ap_show_mpm());
+ ap_rprintf(r, "<dt><strong>MPM Information:</strong> "
+ "<tt>Max Daemons: %d Threaded: %s Forked: %s</tt></dt>\n",
+ max_daemons, threaded ? "yes" : "no",
+ forked ? "yes" : "no");
+ ap_rprintf(r, "<dt><strong>Server Root:</strong> "
+ "<tt>%s</tt></dt>\n", ap_server_root);
+ ap_rprintf(r, "<dt><strong>Config File:</strong> "
+ "<tt>%s</tt></dt>\n", ap_conftree->filename);
+ ap_rputs("</dl><hr />", r);
+ }
+ for (modp = ap_top_module; modp; modp = modp->next) {
+ if (!r->args || !strcasecmp(modp->name, r->args)) {
+ ap_rprintf(r, "<dl><dt><a name=\"%s\"><strong>Module Name:</strong> "
+ "<font size=\"+1\"><tt>%s</tt></font></a></dt>\n",
+ modp->name, modp->name);
+ ap_rputs("<dt><strong>Content handlers:</strong> ", r);
+#ifdef NEVERMORE
+ hand = modp->handlers;
+ if (hand) {
+ while (hand) {
+ if (hand->content_type) {
+ ap_rprintf(r, " <tt>%s</tt>\n", hand->content_type);
+ }
+ else {
+ break;
+ }
+ hand++;
+ if (hand && hand->content_type) {
+ ap_rputs(",", r);
+ }
+ }
+ }
+ else {
+ ap_rputs("<tt> <em>none</em></tt>", r);
+ }
+#else
+ if (module_find_hook(modp, ap_hook_get_handler)) {
+ ap_rputs("<tt> <em>yes</em></tt>", r);
+ }
+ else {
+ ap_rputs("<tt> <em>none</em></tt>", r);
+ }
+#endif
+ ap_rputs("</dt>", r);
+ ap_rputs("<dt><strong>Configuration Phase Participation:</strong>\n",
+ r);
+ if (modp->create_dir_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Create Directory Config</tt>", r);
+ comma = 1;
+ }
+ if (modp->merge_dir_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Merge Directory Configs</tt>", r);
+ comma = 1;
+ }
+ if (modp->create_server_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Create Server Config</tt>", r);
+ comma = 1;
+ }
+ if (modp->merge_server_config) {
+ if (comma) {
+ ap_rputs(", ", r);
+ }
+ ap_rputs("<tt>Merge Server Configs</tt>", r);
+ comma = 1;
+ }
+ if (!comma)
+ ap_rputs("<tt> <em>none</em></tt>", r);
+ comma = 0;
+ ap_rputs("</dt>", r);
+
+ module_request_hook_participate(r, modp);
+
+ cmd = modp->cmds;
+ if (cmd) {
+ ap_rputs("<dt><strong>Module Directives:</strong></dt>", r);
+ while (cmd) {
+ if (cmd->name) {
+ ap_rputs("<dd><tt>", r);
+ mod_info_html_cmd_string(r, cmd->name, 0);
+ ap_rputs(" - <i>", r);
+ if (cmd->errmsg) {
+ ap_rputs(cmd->errmsg, r);
+ }
+ ap_rputs("</i></tt></dd>\n", r);
+ }
+ else {
+ break;
+ }
+ cmd++;
+ }
+ ap_rputs("<dt><strong>Current Configuration:</strong></dt>\n", r);
+ mod_info_module_cmds(r, modp->cmds, ap_conftree);
+ }
+ else {
+ ap_rputs("<dt><strong>Module Directives:</strong> <tt>none</tt></dt>", r);
+ }
+ more_info = find_more_info(serv, modp->name);
+ if (more_info) {
+ ap_rputs("<dt><strong>Additional Information:</strong>\n</dt><dd>",
+ r);
+ ap_rputs(more_info, r);
+ ap_rputs("</dd>", r);
+ }
+ ap_rputs("</dl><hr />\n", r);
+ if (r->args) {
+ break;
+ }
+ }
+ }
+ if (!modp && r->args && strcasecmp(r->args, "server")) {
+ ap_rputs("<p><b>No such module</b></p>\n", r);
+ }
+ }
+ else {
+ ap_rputs("<dl><dt>Server Module List</dt>", r);
+ for (modp = ap_top_module; modp; modp = modp->next) {
+ ap_rputs("<dd>", r);
+ ap_rputs(modp->name, r);
+ ap_rputs("</dd>", r);
+ }
+ ap_rputs("</dl><hr />", r);
+ }
+ ap_rputs(ap_psignature("",r), r);
+ ap_rputs("</body></html>\n", r);
+ /* Done, turn off timeout, close file and return */
+ return 0;
+}
+
+static const char *add_module_info(cmd_parms *cmd, void *dummy,
+ const char *name, const char *info)
+{
+ server_rec *s = cmd->server;
+ info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
+ &info_module);
+ info_entry *new = apr_array_push(conf->more_info);
+
+ new->name = name;
+ new->info = info;
+ return NULL;
+}
+
+static const command_rec info_cmds[] =
+{
+ AP_INIT_TAKE2("AddModuleInfo", add_module_info, NULL, RSRC_CONF,
+ "a module name and additional information on that module"),
+ {NULL}
+};
+
+static void register_hooks(apr_pool_t *p)
+{
+ ap_hook_handler(display_info, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA info_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ create_info_config, /* server config */
+ merge_info_config, /* merge server config */
+ info_cmds, /* command apr_table_t */
+ register_hooks
+};
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_info.dsp b/rubbos/app/httpd-2.0.64/modules/generators/mod_info.dsp
new file mode 100644
index 00000000..7b6a28ec
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_info.dsp
@@ -0,0 +1,128 @@
+# Microsoft Developer Studio Project File - Name="mod_info" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_info - 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 "mod_info.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 "mod_info.mak" CFG="mod_info - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_info - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_info - 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)" == "mod_info - 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 /Zi /O2 /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_info_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:"Release/mod_info.so" /base:@..\..\os\win32\BaseAddr.ref,mod_info.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Release/mod_info.so" /base:@..\..\os\win32\BaseAddr.ref,mod_info.so /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_info - 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 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_info_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_info.so" /base:@..\..\os\win32\BaseAddr.ref,mod_info.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_info.so" /base:@..\..\os\win32\BaseAddr.ref,mod_info.so
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_info - Win32 Release"
+# Name "mod_info - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_info.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_info.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\win32ver.awk
+
+!IF "$(CFG)" == "mod_info - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_info.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_info.so "info_module for Apache" ../../include/ap_release.h > .\mod_info.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_info.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_info.so "info_module for Apache" ../../include/ap_release.h > .\mod_info.rc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_info.exp b/rubbos/app/httpd-2.0.64/modules/generators/mod_info.exp
new file mode 100644
index 00000000..c304fa77
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_info.exp
@@ -0,0 +1 @@
+info_module
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_status.c b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.c
new file mode 100644
index 00000000..ba978d63
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.c
@@ -0,0 +1,857 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Status Module. Display lots of internal data about how Apache is
+ * performing and the state of all children processes.
+ *
+ * To enable this, add the following lines into any config file:
+ *
+ * <Location /server-status>
+ * SetHandler server-status
+ * </Location>
+ *
+ * You may want to protect this location by password or domain so no one
+ * else can look at it. Then you can access the statistics with a URL like:
+ *
+ * http://your_server_name/server-status
+ *
+ * /server-status - Returns page using tables
+ * /server-status?notable - Returns page for browsers without table support
+ * /server-status?refresh - Returns page with 1 second refresh
+ * /server-status?refresh=6 - Returns page with refresh every 6 seconds
+ * /server-status?auto - Returns page with data for automatic parsing
+ *
+ * Mark Cox, mark@ukweb.com, November 1995
+ *
+ * 12.11.95 Initial version for www.telescope.org
+ * 13.3.96 Updated to remove rprintf's [Mark]
+ * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie]
+ * 18.3.96 Make extra Scoreboard variables #definable
+ * 25.3.96 Make short report have full precision [Ben Laurie suggested]
+ * 25.3.96 Show uptime better [Mark/Ben Laurie]
+ * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested]
+ * 09.4.96 Added message for non-STATUS compiled version
+ * 18.4.96 Added per child and per slot counters [Jim Jagielski]
+ * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.]
+ * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing
+ * piece in short reports [Ben Laurie]
+ * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if
+ * extended STATUS is enabled) [George Burgyan/Jim J.]
+ * 10.8.98 Allow for extended status info at runtime (no more STATUS)
+ * [Jim J.]
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_main.h"
+#include "ap_mpm.h"
+#include "util_script.h"
+#include <time.h>
+#include "scoreboard.h"
+#include "http_log.h"
+#include "mod_status.h"
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "apr_strings.h"
+
+#ifdef NEXT
+#if (NX_CURRENT_COMPILER_RELEASE == 410)
+#ifdef m68k
+#define HZ 64
+#else
+#define HZ 100
+#endif
+#else
+#include <machine/param.h>
+#endif
+#endif /* NEXT */
+
+#define STATUS_MAXLINE 64
+
+#define KBYTE 1024
+#define MBYTE 1048576L
+#define GBYTE 1073741824L
+
+#ifndef DEFAULT_TIME_FORMAT
+#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
+#endif
+
+#define STATUS_MAGIC_TYPE "application/x-httpd-status"
+
+module AP_MODULE_DECLARE_DATA status_module;
+
+int server_limit, thread_limit;
+
+#ifdef HAVE_TIMES
+/* ugh... need to know if we're running with a pthread implementation
+ * such as linuxthreads that treats individual threads as distinct
+ * processes; that affects how we add up CPU time in a process
+ */
+static pid_t child_pid;
+#endif
+
+/* Implement 'ap_run_status_hook'. */
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ap, STATUS, int, status_hook,
+ (request_rec *r, int flags),
+ (r, flags),
+ OK, DECLINED)
+
+/*
+ * command-related code. This is here to prevent use of ExtendedStatus
+ * without status_module included.
+ */
+static const char *set_extended_status(cmd_parms *cmd, void *dummy, int arg)
+{
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ if (err != NULL) {
+ return err;
+ }
+ ap_extended_status = arg;
+ return NULL;
+}
+
+static const command_rec status_module_cmds[] =
+{
+ AP_INIT_FLAG("ExtendedStatus", set_extended_status, NULL, RSRC_CONF,
+ "\"On\" to enable extended status information, \"Off\" to disable"),
+ {NULL}
+};
+
+/* Format the number of bytes nicely */
+static void format_byte_out(request_rec *r, apr_off_t bytes)
+{
+ if (bytes < (5 * KBYTE))
+ ap_rprintf(r, "%d B", (int) bytes);
+ else if (bytes < (MBYTE / 2))
+ ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE);
+ else if (bytes < (GBYTE / 2))
+ ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE);
+ else
+ ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE);
+}
+
+static void format_kbyte_out(request_rec *r, apr_off_t kbytes)
+{
+ if (kbytes < KBYTE)
+ ap_rprintf(r, "%d kB", (int) kbytes);
+ else if (kbytes < MBYTE)
+ ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE);
+ else
+ ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE);
+}
+
+static void show_time(request_rec *r, apr_interval_time_t tsecs)
+{
+ int days, hrs, mins, secs;
+
+ secs = (int)(tsecs % 60);
+ tsecs /= 60;
+ mins = (int)(tsecs % 60);
+ tsecs /= 60;
+ hrs = (int)(tsecs % 24);
+ days = (int)(tsecs / 24);
+
+ if (days)
+ ap_rprintf(r, " %d day%s", days, days == 1 ? "" : "s");
+
+ if (hrs)
+ ap_rprintf(r, " %d hour%s", hrs, hrs == 1 ? "" : "s");
+
+ if (mins)
+ ap_rprintf(r, " %d minute%s", mins, mins == 1 ? "" : "s");
+
+ if (secs)
+ ap_rprintf(r, " %d second%s", secs, secs == 1 ? "" : "s");
+}
+
+/* Main handler for x-httpd-status requests */
+
+/* ID values for command table */
+
+#define STAT_OPT_END -1
+#define STAT_OPT_REFRESH 0
+#define STAT_OPT_NOTABLE 1
+#define STAT_OPT_AUTO 2
+
+struct stat_opt {
+ int id;
+ const char *form_data_str;
+ const char *hdr_out_str;
+};
+
+static const struct stat_opt status_options[] = /* see #defines above */
+{
+ {STAT_OPT_REFRESH, "refresh", "Refresh"},
+ {STAT_OPT_NOTABLE, "notable", NULL},
+ {STAT_OPT_AUTO, "auto", NULL},
+ {STAT_OPT_END, NULL, NULL}
+};
+
+static char status_flags[SERVER_NUM_STATUS];
+
+static int status_handler(request_rec *r)
+{
+ const char *loc;
+ apr_time_t nowtime;
+ apr_interval_time_t up_time;
+ int j, i, res;
+ int ready;
+ int busy;
+ unsigned long count;
+ unsigned long lres, my_lres, conn_lres;
+ apr_off_t bytes, my_bytes, conn_bytes;
+ apr_off_t bcount, kbcount;
+ long req_time;
+#ifdef HAVE_TIMES
+ float tick;
+ int times_per_thread = getpid() != child_pid;
+#endif
+ int short_report;
+ int no_table_report;
+ worker_score *ws_record;
+ process_score *ps_record;
+ char *stat_buffer;
+ pid_t *pid_buffer;
+ clock_t tu, ts, tcu, tcs;
+
+ if (strcmp(r->handler, STATUS_MAGIC_TYPE) &&
+ strcmp(r->handler, "server-status")) {
+ return DECLINED;
+ }
+
+#ifdef HAVE_TIMES
+#ifdef _SC_CLK_TCK
+ tick = sysconf(_SC_CLK_TCK);
+#else
+ tick = HZ;
+#endif
+#endif
+
+ ready = 0;
+ busy = 0;
+ count = 0;
+ bcount = 0;
+ kbcount = 0;
+ short_report = 0;
+ no_table_report = 0;
+
+ pid_buffer = apr_palloc(r->pool, server_limit * sizeof(pid_t));
+ stat_buffer = apr_palloc(r->pool, server_limit * thread_limit * sizeof(char));
+
+ nowtime = apr_time_now();
+ tu = ts = tcu = tcs = 0;
+
+ if (!ap_exists_scoreboard_image()) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Server status unavailable in inetd mode");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ r->allowed = (AP_METHOD_BIT << M_GET);
+ if (r->method_number != M_GET)
+ return DECLINED;
+
+ ap_set_content_type(r, "text/html; charset=ISO-8859-1");
+
+ /*
+ * Simple table-driven form data set parser that lets you alter the header
+ */
+
+ if (r->args) {
+ i = 0;
+ while (status_options[i].id != STAT_OPT_END) {
+ if ((loc = ap_strstr_c(r->args,
+ status_options[i].form_data_str)) != NULL) {
+ switch (status_options[i].id) {
+ case STAT_OPT_REFRESH: {
+ apr_size_t len = strlen(status_options[i].form_data_str);
+ long t = 0;
+
+ if (*(loc + len ) == '=') {
+ t = atol(loc + len + 1);
+ }
+ apr_table_set(r->headers_out,
+ status_options[i].hdr_out_str,
+ apr_ltoa(r->pool, t < 1 ? 10 : t));
+ break;
+ }
+ case STAT_OPT_NOTABLE:
+ no_table_report = 1;
+ break;
+ case STAT_OPT_AUTO:
+ ap_set_content_type(r, "text/plain; charset=ISO-8859-1");
+ short_report = 1;
+ break;
+ }
+ }
+
+ i++;
+ }
+ }
+
+ for (i = 0; i < server_limit; ++i) {
+#ifdef HAVE_TIMES
+ clock_t proc_tu = 0, proc_ts = 0, proc_tcu = 0, proc_tcs = 0;
+ clock_t tmp_tu, tmp_ts, tmp_tcu, tmp_tcs;
+#endif
+
+ ps_record = ap_get_scoreboard_process(i);
+ for (j = 0; j < thread_limit; ++j) {
+ int indx = (i * thread_limit) + j;
+
+ ws_record = ap_get_scoreboard_worker(i, j);
+ res = ws_record->status;
+ stat_buffer[indx] = status_flags[res];
+
+ if (!ps_record->quiescing
+ && ps_record->pid) {
+ if (res == SERVER_READY
+ && ps_record->generation == ap_my_generation)
+ ready++;
+ else if (res != SERVER_DEAD &&
+ res != SERVER_STARTING &&
+ res != SERVER_IDLE_KILL)
+ busy++;
+ }
+
+ /* XXX what about the counters for quiescing/seg faulted
+ * processes? should they be counted or not? GLA
+ */
+ if (ap_extended_status) {
+ lres = ws_record->access_count;
+ bytes = ws_record->bytes_served;
+
+ if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) {
+#ifdef HAVE_TIMES
+ tmp_tu = ws_record->times.tms_utime;
+ tmp_ts = ws_record->times.tms_stime;
+ tmp_tcu = ws_record->times.tms_cutime;
+ tmp_tcs = ws_record->times.tms_cstime;
+
+ if (times_per_thread) {
+ proc_tu += tmp_tu;
+ proc_ts += tmp_ts;
+ proc_tcu += tmp_tcu;
+ proc_tcs += proc_tcs;
+ }
+ else {
+ if (tmp_tu > proc_tu ||
+ tmp_ts > proc_ts ||
+ tmp_tcu > proc_tcu ||
+ tmp_tcs > proc_tcs) {
+ proc_tu = tmp_tu;
+ proc_ts = tmp_ts;
+ proc_tcu = tmp_tcu;
+ proc_tcs = proc_tcs;
+ }
+ }
+#endif /* HAVE_TIMES */
+
+ count += lres;
+ bcount += bytes;
+
+ if (bcount >= KBYTE) {
+ kbcount += (bcount >> 10);
+ bcount = bcount & 0x3ff;
+ }
+ }
+ }
+ }
+#ifdef HAVE_TIMES
+ tu += proc_tu;
+ ts += proc_ts;
+ tcu += proc_tcu;
+ tcs += proc_tcs;
+#endif
+ pid_buffer[i] = ps_record->pid;
+ }
+
+ /* up_time in seconds */
+ up_time = (apr_uint32_t) apr_time_sec(nowtime -
+ ap_scoreboard_image->global->restart_time);
+
+ if (!short_report) {
+ ap_rputs(DOCTYPE_HTML_3_2
+ "<html><head>\n<title>Apache Status</title>\n</head><body>\n",
+ r);
+ ap_rputs("<h1>Apache Server Status for ", r);
+ ap_rvputs(r, ap_get_server_name(r), "</h1>\n\n", NULL);
+ ap_rvputs(r, "<dl><dt>Server Version: ",
+ ap_get_server_version(), "</dt>\n", NULL);
+ ap_rvputs(r, "<dt>Server Built: ",
+ ap_get_server_built(), "\n</dt></dl><hr /><dl>\n", NULL);
+ ap_rvputs(r, "<dt>Current Time: ",
+ ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0),
+ "</dt>\n", NULL);
+ ap_rvputs(r, "<dt>Restart Time: ",
+ ap_ht_time(r->pool,
+ ap_scoreboard_image->global->restart_time,
+ DEFAULT_TIME_FORMAT, 0),
+ "</dt>\n", NULL);
+ ap_rprintf(r, "<dt>Parent Server Generation: %d</dt>\n",
+ (int)ap_my_generation);
+ ap_rputs("<dt>Server uptime: ", r);
+ show_time(r, up_time);
+ ap_rputs("</dt>\n", r);
+ }
+
+ if (ap_extended_status) {
+ if (short_report) {
+ ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %"
+ APR_OFF_T_FMT "\n",
+ count, kbcount);
+
+#ifdef HAVE_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ if (ts || tu || tcu || tcs)
+ ap_rprintf(r, "CPULoad: %g\n",
+ (tu + ts + tcu + tcs) / tick / up_time * 100.);
+#endif
+
+ ap_rprintf(r, "Uptime: %ld\n", (long) (up_time));
+ if (up_time > 0)
+ ap_rprintf(r, "ReqPerSec: %g\n",
+ (float) count / (float) up_time);
+
+ if (up_time > 0)
+ ap_rprintf(r, "BytesPerSec: %g\n",
+ KBYTE * (float) kbcount / (float) up_time);
+
+ if (count > 0)
+ ap_rprintf(r, "BytesPerReq: %g\n",
+ KBYTE * (float) kbcount / (float) count);
+ }
+ else { /* !short_report */
+ ap_rprintf(r, "<dt>Total accesses: %lu - Total Traffic: ", count);
+ format_kbyte_out(r, kbcount);
+ ap_rputs("</dt>\n", r);
+
+#ifdef HAVE_TIMES
+ /* Allow for OS/2 not having CPU stats */
+ ap_rprintf(r, "<dt>CPU Usage: u%g s%g cu%g cs%g",
+ tu / tick, ts / tick, tcu / tick, tcs / tick);
+
+ if (ts || tu || tcu || tcs)
+ ap_rprintf(r, " - %.3g%% CPU load</dt>\n",
+ (tu + ts + tcu + tcs) / tick / up_time * 100.);
+#endif
+
+ if (up_time > 0)
+ ap_rprintf(r, "<dt>%.3g requests/sec - ",
+ (float) count / (float) up_time);
+
+ if (up_time > 0) {
+ format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
+ / (float) up_time));
+ ap_rputs("/second - ", r);
+ }
+
+ if (count > 0) {
+ format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
+ / (float) count));
+ ap_rputs("/request", r);
+ }
+
+ ap_rputs("</dt>\n", r);
+ } /* short_report */
+ } /* ap_extended_status */
+
+ if (!short_report)
+ ap_rprintf(r, "<dt>%d requests currently being processed, "
+ "%d idle workers</dt>\n", busy, ready);
+ else
+ ap_rprintf(r, "BusyWorkers: %d\nIdleWorkers: %d\n", busy, ready);
+
+ /* send the scoreboard 'table' out */
+ if (!short_report)
+ ap_rputs("</dl><pre>", r);
+ else
+ ap_rputs("Scoreboard: ", r);
+
+ for (i = 0; i < server_limit; ++i) {
+ for (j = 0; j < thread_limit; ++j) {
+ int indx = (i * thread_limit) + j;
+ ap_rputc(stat_buffer[indx], r);
+ if ((indx % STATUS_MAXLINE == (STATUS_MAXLINE - 1))
+ && !short_report)
+ ap_rputs("\n", r);
+ }
+ }
+
+ if (short_report)
+ ap_rputs("\n", r);
+ else {
+ ap_rputs("</pre>\n", r);
+ ap_rputs("<p>Scoreboard Key:<br />\n", r);
+ ap_rputs("\"<b><code>_</code></b>\" Waiting for Connection, \n", r);
+ ap_rputs("\"<b><code>S</code></b>\" Starting up, \n", r);
+ ap_rputs("\"<b><code>R</code></b>\" Reading Request,<br />\n", r);
+ ap_rputs("\"<b><code>W</code></b>\" Sending Reply, \n", r);
+ ap_rputs("\"<b><code>K</code></b>\" Keepalive (read), \n", r);
+ ap_rputs("\"<b><code>D</code></b>\" DNS Lookup,<br />\n", r);
+ ap_rputs("\"<b><code>C</code></b>\" Closing connection, \n", r);
+ ap_rputs("\"<b><code>L</code></b>\" Logging, \n", r);
+ ap_rputs("\"<b><code>G</code></b>\" Gracefully finishing,<br /> \n", r);
+ ap_rputs("\"<b><code>I</code></b>\" Idle cleanup of worker, \n", r);
+ ap_rputs("\"<b><code>.</code></b>\" Open slot with no current process</p>\n", r);
+ ap_rputs("<p />\n", r);
+ if (!ap_extended_status) {
+ int j;
+ int k = 0;
+ ap_rputs("PID Key: <br />\n", r);
+ ap_rputs("<pre>\n", r);
+ for (i = 0; i < server_limit; ++i) {
+ for (j = 0; j < thread_limit; ++j) {
+ int indx = (i * thread_limit) + j;
+
+ if (stat_buffer[indx] != '.') {
+ ap_rprintf(r, " %" APR_PID_T_FMT
+ " in state: %c ", pid_buffer[i],
+ stat_buffer[indx]);
+
+ if (++k >= 3) {
+ ap_rputs("\n", r);
+ k = 0;
+ } else
+ ap_rputs(",", r);
+ }
+ }
+ }
+
+ ap_rputs("\n", r);
+ ap_rputs("</pre>\n", r);
+ }
+ }
+
+ if (ap_extended_status && !short_report) {
+ if (no_table_report)
+ ap_rputs("<hr /><h2>Server Details</h2>\n\n", r);
+ else
+ ap_rputs("\n\n<table border=\"0\"><tr>"
+ "<th>Srv</th><th>PID</th><th>Acc</th>"
+ "<th>M</th>"
+#ifdef HAVE_TIMES
+ "<th>CPU\n</th>"
+#endif
+ "<th>SS</th><th>Req</th>"
+ "<th>Conn</th><th>Child</th><th>Slot</th>"
+ "<th>Client</th><th>VHost</th>"
+ "<th>Request</th></tr>\n\n", r);
+
+ for (i = 0; i < server_limit; ++i) {
+ for (j = 0; j < thread_limit; ++j) {
+ ws_record = ap_get_scoreboard_worker(i, j);
+
+ if (ws_record->access_count == 0 &&
+ (ws_record->status == SERVER_READY ||
+ ws_record->status == SERVER_DEAD)) {
+ continue;
+ }
+
+ ps_record = ap_get_scoreboard_process(i);
+
+ if (ws_record->start_time == 0L)
+ req_time = 0L;
+ else
+ req_time = (long)
+ ((ws_record->stop_time -
+ ws_record->start_time) / 1000);
+ if (req_time < 0L)
+ req_time = 0L;
+
+ lres = ws_record->access_count;
+ my_lres = ws_record->my_access_count;
+ conn_lres = ws_record->conn_count;
+ bytes = ws_record->bytes_served;
+ my_bytes = ws_record->my_bytes_served;
+ conn_bytes = ws_record->conn_bytes;
+
+ if (no_table_report) {
+ if (ws_record->status == SERVER_DEAD)
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (-): %d|%lu|%lu [",
+ i, (int)ps_record->generation,
+ (int)conn_lres, my_lres, lres);
+ else
+ ap_rprintf(r,
+ "<b>Server %d-%d</b> (%"
+ APR_PID_T_FMT "): %d|%lu|%lu [",
+ i, (int) ps_record->generation,
+ ps_record->pid,
+ (int)conn_lres, my_lres, lres);
+
+ switch (ws_record->status) {
+ case SERVER_READY:
+ ap_rputs("Ready", r);
+ break;
+ case SERVER_STARTING:
+ ap_rputs("Starting", r);
+ break;
+ case SERVER_BUSY_READ:
+ ap_rputs("<b>Read</b>", r);
+ break;
+ case SERVER_BUSY_WRITE:
+ ap_rputs("<b>Write</b>", r);
+ break;
+ case SERVER_BUSY_KEEPALIVE:
+ ap_rputs("<b>Keepalive</b>", r);
+ break;
+ case SERVER_BUSY_LOG:
+ ap_rputs("<b>Logging</b>", r);
+ break;
+ case SERVER_BUSY_DNS:
+ ap_rputs("<b>DNS lookup</b>", r);
+ break;
+ case SERVER_CLOSING:
+ ap_rputs("<b>Closing</b>", r);
+ break;
+ case SERVER_DEAD:
+ ap_rputs("Dead", r);
+ break;
+ case SERVER_GRACEFUL:
+ ap_rputs("Graceful", r);
+ break;
+ case SERVER_IDLE_KILL:
+ ap_rputs("Dying", r);
+ break;
+ default:
+ ap_rputs("?STATE?", r);
+ break;
+ }
+
+ ap_rprintf(r, "] "
+#ifdef HAVE_TIMES
+ "u%g s%g cu%g cs%g"
+#endif
+ "\n %ld %ld (",
+#ifdef HAVE_TIMES
+ ws_record->times.tms_utime / tick,
+ ws_record->times.tms_stime / tick,
+ ws_record->times.tms_cutime / tick,
+ ws_record->times.tms_cstime / tick,
+#endif
+ (long)apr_time_sec(nowtime -
+ ws_record->last_used),
+ (long) req_time);
+
+ format_byte_out(r, conn_bytes);
+ ap_rputs("|", r);
+ format_byte_out(r, my_bytes);
+ ap_rputs("|", r);
+ format_byte_out(r, bytes);
+ ap_rputs(")\n", r);
+ ap_rprintf(r,
+ " <i>%s {%s}</i> <b>[%s]</b><br />\n\n",
+ ap_escape_html(r->pool,
+ ws_record->client),
+ ap_escape_html(r->pool,
+ ap_escape_logitem(r->pool,
+ ws_record->request)),
+ ap_escape_html(r->pool,
+ ws_record->vhost));
+ }
+ else { /* !no_table_report */
+ if (ws_record->status == SERVER_DEAD)
+ ap_rprintf(r,
+ "<tr><td><b>%d-%d</b></td><td>-</td><td>%d/%lu/%lu",
+ i, (int)ps_record->generation,
+ (int)conn_lres, my_lres, lres);
+ else
+ ap_rprintf(r,
+ "<tr><td><b>%d-%d</b></td><td>%"
+ APR_PID_T_FMT
+ "</td><td>%d/%lu/%lu",
+ i, (int)ps_record->generation,
+ ps_record->pid, (int)conn_lres,
+ my_lres, lres);
+
+ switch (ws_record->status) {
+ case SERVER_READY:
+ ap_rputs("</td><td>_", r);
+ break;
+ case SERVER_STARTING:
+ ap_rputs("</td><td><b>S</b>", r);
+ break;
+ case SERVER_BUSY_READ:
+ ap_rputs("</td><td><b>R</b>", r);
+ break;
+ case SERVER_BUSY_WRITE:
+ ap_rputs("</td><td><b>W</b>", r);
+ break;
+ case SERVER_BUSY_KEEPALIVE:
+ ap_rputs("</td><td><b>K</b>", r);
+ break;
+ case SERVER_BUSY_LOG:
+ ap_rputs("</td><td><b>L</b>", r);
+ break;
+ case SERVER_BUSY_DNS:
+ ap_rputs("</td><td><b>D</b>", r);
+ break;
+ case SERVER_CLOSING:
+ ap_rputs("</td><td><b>C</b>", r);
+ break;
+ case SERVER_DEAD:
+ ap_rputs("</td><td>.", r);
+ break;
+ case SERVER_GRACEFUL:
+ ap_rputs("</td><td>G", r);
+ break;
+ case SERVER_IDLE_KILL:
+ ap_rputs("</td><td>I", r);
+ break;
+ default:
+ ap_rputs("</td><td>?", r);
+ break;
+ }
+
+ ap_rprintf(r,
+ "\n</td>"
+#ifdef HAVE_TIMES
+ "<td>%.2f</td>"
+#endif
+ "<td>%ld</td><td>%ld",
+#ifdef HAVE_TIMES
+ (ws_record->times.tms_utime +
+ ws_record->times.tms_stime +
+ ws_record->times.tms_cutime +
+ ws_record->times.tms_cstime) / tick,
+#endif
+ (long)apr_time_sec(nowtime -
+ ws_record->last_used),
+ (long)req_time);
+
+ ap_rprintf(r, "</td><td>%-1.1f</td><td>%-2.2f</td><td>%-2.2f\n",
+ (float)conn_bytes / KBYTE, (float) my_bytes / MBYTE,
+ (float)bytes / MBYTE);
+
+ if (ws_record->status == SERVER_BUSY_READ)
+ ap_rprintf(r,
+ "</td><td>?</td><td nowrap>?</td><td nowrap>..reading.. </td></tr>\n\n");
+ else
+ ap_rprintf(r,
+ "</td><td>%s</td><td nowrap>%s</td><td nowrap>%s</td></tr>\n\n",
+ ap_escape_html(r->pool,
+ ws_record->client),
+ ap_escape_html(r->pool,
+ ws_record->vhost),
+ ap_escape_html(r->pool,
+ ap_escape_logitem(r->pool,
+ ws_record->request)));
+ } /* no_table_report */
+ } /* for (j...) */
+ } /* for (i...) */
+
+ if (!no_table_report) {
+ ap_rputs("</table>\n \
+<hr /> \
+<table>\n \
+<tr><th>Srv</th><td>Child Server number - generation</td></tr>\n \
+<tr><th>PID</th><td>OS process ID</td></tr>\n \
+<tr><th>Acc</th><td>Number of accesses this connection / this child / this slot</td></tr>\n \
+<tr><th>M</th><td>Mode of operation</td></tr>\n"
+
+#ifdef HAVE_TIMES
+"<tr><th>CPU</th><td>CPU usage, number of seconds</td></tr>\n"
+#endif
+
+"<tr><th>SS</th><td>Seconds since beginning of most recent request</td></tr>\n \
+<tr><th>Req</th><td>Milliseconds required to process most recent request</td></tr>\n \
+<tr><th>Conn</th><td>Kilobytes transferred this connection</td></tr>\n \
+<tr><th>Child</th><td>Megabytes transferred this child</td></tr>\n \
+<tr><th>Slot</th><td>Total megabytes transferred this slot</td></tr>\n \
+</table>\n", r);
+ }
+ } /* if (ap_extended_status && !short_report) */
+ else {
+
+ if (!short_report) {
+ ap_rputs("<hr />To obtain a full report with current status "
+ "information you need to use the "
+ "<code>ExtendedStatus On</code> directive.\n", r);
+ }
+ }
+
+ {
+ /* Run extension hooks to insert extra content. */
+ int flags =
+ (short_report ? AP_STATUS_SHORT : 0) |
+ (no_table_report ? AP_STATUS_NOTABLE : 0) |
+ (ap_extended_status ? AP_STATUS_EXTENDED : 0);
+
+ ap_run_status_hook(r, flags);
+ }
+
+ if (!short_report) {
+ ap_rputs(ap_psignature("<hr />\n",r), r);
+ ap_rputs("</body></html>\n", r);
+ }
+
+ return 0;
+}
+
+
+static int status_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
+ server_rec *s)
+{
+ status_flags[SERVER_DEAD] = '.'; /* We don't want to assume these are in */
+ status_flags[SERVER_READY] = '_'; /* any particular order in scoreboard.h */
+ status_flags[SERVER_STARTING] = 'S';
+ status_flags[SERVER_BUSY_READ] = 'R';
+ status_flags[SERVER_BUSY_WRITE] = 'W';
+ status_flags[SERVER_BUSY_KEEPALIVE] = 'K';
+ status_flags[SERVER_BUSY_LOG] = 'L';
+ status_flags[SERVER_BUSY_DNS] = 'D';
+ status_flags[SERVER_CLOSING] = 'C';
+ status_flags[SERVER_GRACEFUL] = 'G';
+ status_flags[SERVER_IDLE_KILL] = 'I';
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+ return OK;
+}
+
+#ifdef HAVE_TIMES
+static void status_child_init(apr_pool_t *p, server_rec *s)
+{
+ child_pid = getpid();
+}
+#endif
+
+static void register_hooks(apr_pool_t *p)
+{
+ ap_hook_handler(status_handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_post_config(status_init, NULL, NULL, APR_HOOK_MIDDLE);
+#ifdef HAVE_TIMES
+ ap_hook_child_init(status_child_init, NULL, NULL, APR_HOOK_MIDDLE);
+#endif
+}
+
+module AP_MODULE_DECLARE_DATA status_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL, /* dir config creater */
+ NULL, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ status_module_cmds, /* command table */
+ register_hooks /* register_hooks */
+};
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_status.dsp b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.dsp
new file mode 100644
index 00000000..5a0eef5d
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.dsp
@@ -0,0 +1,128 @@
+# Microsoft Developer Studio Project File - Name="mod_status" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_status - 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 "mod_status.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 "mod_status.mak" CFG="mod_status - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_status - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_status - 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)" == "mod_status - 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 /Zi /O2 /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STATUS_DECLARE_EXPORT" /Fd"Release\mod_status_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:"Release/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /debug /out:"Release/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status.so /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_status - 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 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STATUS_DECLARE_EXPORT" /Fd"Debug\mod_status_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:"Debug/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status.so
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_status - Win32 Release"
+# Name "mod_status - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_status.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mod_status.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\win32ver.awk
+
+!IF "$(CFG)" == "mod_status - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_status.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_status.so "status_module for Apache" ../../include/ap_release.h > .\mod_status.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_status.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_status.so "status_module for Apache" ../../include/ap_release.h > .\mod_status.rc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_status.exp b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.exp
new file mode 100644
index 00000000..54380936
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.exp
@@ -0,0 +1 @@
+status_module
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_status.h b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.h
new file mode 100644
index 00000000..03911a02
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.h
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MOD_STATUS_H
+#define MOD_STATUS_H
+
+#include "ap_config.h"
+#include "httpd.h"
+
+#define AP_STATUS_SHORT (0x1) /* short, non-HTML report requested */
+#define AP_STATUS_NOTABLE (0x2) /* HTML report without tables */
+#define AP_STATUS_EXTENDED (0x4) /* detailed report */
+
+#if !defined(WIN32)
+#define STATUS_DECLARE(type) type
+#define STATUS_DECLARE_NONSTD(type) type
+#define STATUS_DECLARE_DATA
+#elif defined(STATUS_DECLARE_STATIC)
+#define STATUS_DECLARE(type) type __stdcall
+#define STATUS_DECLARE_NONSTD(type) type
+#define STATUS_DECLARE_DATA
+#elif defined(STATUS_DECLARE_EXPORT)
+#define STATUS_DECLARE(type) __declspec(dllexport) type __stdcall
+#define STATUS_DECLARE_NONSTD(type) __declspec(dllexport) type
+#define STATUS_DECLARE_DATA __declspec(dllexport)
+#else
+#define STATUS_DECLARE(type) __declspec(dllimport) type __stdcall
+#define STATUS_DECLARE_NONSTD(type) __declspec(dllimport) type
+#define STATUS_DECLARE_DATA __declspec(dllimport)
+#endif
+
+/* Optional hooks which can insert extra content into the mod_status
+ * output. FLAGS will be set to the bitwise OR of any of the
+ * AP_STATUS_* flags.
+ *
+ * Implementations of this hook should generate content using
+ * functions in the ap_rputs/ap_rprintf family; each hook should
+ * return OK or DECLINED. */
+APR_DECLARE_EXTERNAL_HOOK(ap, STATUS, int, status_hook,
+ (request_rec *r, int flags))
+#endif
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_status.la b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.la
new file mode 100644
index 00000000..fc5f7173
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.la
@@ -0,0 +1,35 @@
+# mod_status.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='mod_status.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -L/bottlenecks/rubbos/app/httpd-2.0.64/srclib/apr-util/xml/expat/lib'
+
+# Version information for mod_status.
+current=
+age=
+revision=
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir=''
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_status.lo b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.lo
new file mode 100644
index 00000000..a740c8dd
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.lo
@@ -0,0 +1,12 @@
+# mod_status.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object='.libs/mod_status.o'
+
+# Name of the non-PIC object.
+non_pic_object='mod_status.o'
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_status.o b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.o
new file mode 100644
index 00000000..107ccfef
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.o
Binary files differ
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.c b/rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.c
new file mode 100644
index 00000000..308c3520
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.c
@@ -0,0 +1,138 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CORE_PRIVATE
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_request.h"
+#include "apr_strings.h"
+#include "unixd.h"
+#include "mpm_common.h"
+#include "mod_suexec.h"
+
+module AP_MODULE_DECLARE_DATA suexec_module;
+
+/*
+ * Create a configuration specific to this module for a server or directory
+ * location, and fill it with the default settings.
+ */
+static void *mkconfig(apr_pool_t *p)
+{
+ suexec_config_t *cfg = apr_palloc(p, sizeof(suexec_config_t));
+
+ cfg->active = 0;
+ return cfg;
+}
+
+/*
+ * Respond to a callback to create configuration record for a server or
+ * vhost environment.
+ */
+static void *create_mconfig_for_server(apr_pool_t *p, server_rec *s)
+{
+ return mkconfig(p);
+}
+
+/*
+ * Respond to a callback to create a config record for a specific directory.
+ */
+static void *create_mconfig_for_directory(apr_pool_t *p, char *dir)
+{
+ return mkconfig(p);
+}
+
+static const char *set_suexec_ugid(cmd_parms *cmd, void *mconfig,
+ const char *uid, const char *gid)
+{
+ suexec_config_t *cfg = (suexec_config_t *) mconfig;
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+
+ if (err != NULL) {
+ return err;
+ }
+ if (unixd_config.suexec_enabled) {
+ cfg->ugid.uid = ap_uname2id(uid);
+ cfg->ugid.gid = ap_gname2id(gid);
+ cfg->ugid.userdir = 0;
+ cfg->active = 1;
+ }
+ else {
+ fprintf(stderr,
+ "Warning: SuexecUserGroup directive requires SUEXEC wrapper.\n");
+ }
+ return NULL;
+}
+
+static ap_unix_identity_t *get_suexec_id_doer(const request_rec *r)
+{
+ suexec_config_t *cfg =
+ (suexec_config_t *) ap_get_module_config(r->per_dir_config, &suexec_module);
+
+ return cfg->active ? &cfg->ugid : NULL;
+}
+
+#define SUEXEC_POST_CONFIG_USERDATA "suexec_post_config_userdata"
+static int suexec_post_config(apr_pool_t *p, apr_pool_t *plog,
+ apr_pool_t *ptemp, server_rec *s)
+{
+ void *reported;
+
+ apr_pool_userdata_get(&reported, SUEXEC_POST_CONFIG_USERDATA,
+ s->process->pool);
+
+ if ((reported == NULL) && unixd_config.suexec_enabled) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s,
+ "suEXEC mechanism enabled (wrapper: %s)", SUEXEC_BIN);
+
+ apr_pool_userdata_set((void *)1, SUEXEC_POST_CONFIG_USERDATA,
+ apr_pool_cleanup_null, s->process->pool);
+ }
+
+ return OK;
+}
+#undef SUEXEC_POST_CONFIG_USERDATA
+
+/*
+ * Define the directives specific to this module. This structure is referenced
+ * later by the 'module' structure.
+ */
+static const command_rec suexec_cmds[] =
+{
+ /* XXX - Another important reason not to allow this in .htaccess is that
+ * the ap_[ug]name2id() is not thread-safe */
+ AP_INIT_TAKE2("SuexecUserGroup", set_suexec_ugid, NULL, RSRC_CONF,
+ "User and group for spawned processes"),
+ { NULL }
+};
+
+static void suexec_hooks(apr_pool_t *p)
+{
+ ap_hook_get_suexec_identity(get_suexec_id_doer,NULL,NULL,APR_HOOK_MIDDLE);
+ ap_hook_post_config(suexec_post_config,NULL,NULL,APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA suexec_module =
+{
+ STANDARD20_MODULE_STUFF,
+ create_mconfig_for_directory, /* create per-dir config */
+ NULL, /* merge per-dir config */
+ create_mconfig_for_server, /* server config */
+ NULL, /* merge server config */
+ suexec_cmds, /* command table */
+ suexec_hooks /* register hooks */
+};
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.h b/rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.h
new file mode 100644
index 00000000..6adc9ec4
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_suexec.h
@@ -0,0 +1,23 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "unixd.h"
+
+typedef struct {
+ ap_unix_identity_t ugid;
+ int active;
+} suexec_config_t;
+
diff --git a/rubbos/app/httpd-2.0.64/modules/generators/modules.mk b/rubbos/app/httpd-2.0.64/modules/generators/modules.mk
new file mode 100644
index 00000000..5c4be7c6
--- /dev/null
+++ b/rubbos/app/httpd-2.0.64/modules/generators/modules.mk
@@ -0,0 +1,11 @@
+mod_status.la: mod_status.lo
+ $(MOD_LINK) mod_status.lo $(MOD_STATUS_LDADD)
+mod_autoindex.la: mod_autoindex.lo
+ $(MOD_LINK) mod_autoindex.lo $(MOD_AUTOINDEX_LDADD)
+mod_asis.la: mod_asis.lo
+ $(MOD_LINK) mod_asis.lo $(MOD_ASIS_LDADD)
+mod_cgid.la: mod_cgid.lo
+ $(MOD_LINK) mod_cgid.lo $(MOD_CGID_LDADD)
+DISTCLEAN_TARGETS = modules.mk
+static = mod_status.la mod_autoindex.la mod_asis.la mod_cgid.la
+shared =