diff options
author | hongbotian <hongbo.tianhongbo@huawei.com> | 2015-11-30 01:45:08 -0500 |
---|---|---|
committer | hongbotian <hongbo.tianhongbo@huawei.com> | 2015-11-30 01:45:08 -0500 |
commit | e8ec7aa8e38a93f5b034ac74cebce5de23710317 (patch) | |
tree | aa031937bf856c1f8d6ad7877b8d2cb0224da5ef /rubbos/app/httpd-2.0.64/modules/generators | |
parent | cc40af334e619bb549038238507407866f774f8f (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')
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 Binary files differnew file mode 100644 index 00000000..f7606c14 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.a 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 Binary files differnew file mode 100644 index 00000000..acca9866 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_asis.o 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 Binary files differnew file mode 100644 index 00000000..e4afe274 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.a 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 Binary files differnew file mode 100644 index 00000000..08725d05 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_autoindex.o 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 Binary files differnew file mode 100644 index 00000000..80394ff9 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.a 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 Binary files differnew file mode 100644 index 00000000..ffbaef81 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_cgid.o 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 Binary files differnew file mode 100644 index 00000000..00fe8005 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.a 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 Binary files differnew file mode 100644 index 00000000..107ccfef --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/.libs/mod_status.o 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 Binary files differnew file mode 100644 index 00000000..acca9866 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_asis.o 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("<", r); + } + else if (ch == '>') { + ap_rputs(">", r); + } + else if (ch == '&') { + ap_rputs("&", 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 ä 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(" </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(" ", 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> ", 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> ", 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 Binary files differnew file mode 100644 index 00000000..08725d05 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_autoindex.o 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 Binary files differnew file mode 100644 index 00000000..ffbaef81 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_cgid.o 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("</", r); + } else { + ap_rputs("<", r); + } + } + else if (*s == '>') { + ap_rputs(">", r); + } + else if (*s == '&') { + ap_rputs("&", r); + } + else if (*s == ' ') { + if (close) { + ap_rputs(">", 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> %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> %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 " + "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 Binary files differnew file mode 100644 index 00000000..107ccfef --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/generators/mod_status.o 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 = |