From 6beeb1b708550be0d4a53b272283e17e5e35fe17 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 17:01:30 +0200 Subject: Adding upstream version 2.4.57. Signed-off-by: Daniel Baumann --- modules/core/Makefile.in | 3 + modules/core/NWGNUmakefile | 257 ++++++++++ modules/core/config.m4 | 60 +++ modules/core/mod_macro.c | 950 ++++++++++++++++++++++++++++++++++++ modules/core/mod_macro.dep | 45 ++ modules/core/mod_macro.dsp | 111 +++++ modules/core/mod_macro.mak | 353 ++++++++++++++ modules/core/mod_so.c | 442 +++++++++++++++++ modules/core/mod_so.h | 38 ++ modules/core/mod_watchdog.c | 718 +++++++++++++++++++++++++++ modules/core/mod_watchdog.dep | 59 +++ modules/core/mod_watchdog.dsp | 115 +++++ modules/core/mod_watchdog.h | 213 ++++++++ modules/core/mod_watchdog.mak | 353 ++++++++++++++ modules/core/test/Makefile | 67 +++ modules/core/test/conf/inc63_1.conf | 5 + modules/core/test/conf/inc63_2.conf | 3 + modules/core/test/conf/test01.conf | 3 + modules/core/test/conf/test02.conf | 3 + modules/core/test/conf/test03.conf | 5 + modules/core/test/conf/test04.conf | 5 + modules/core/test/conf/test05.conf | 5 + modules/core/test/conf/test06.conf | 6 + modules/core/test/conf/test07.conf | 3 + modules/core/test/conf/test08.conf | 3 + modules/core/test/conf/test09.conf | 6 + modules/core/test/conf/test10.conf | 10 + modules/core/test/conf/test11.conf | 15 + modules/core/test/conf/test12.conf | 12 + modules/core/test/conf/test13.conf | 18 + modules/core/test/conf/test14.conf | 23 + modules/core/test/conf/test15.conf | 9 + modules/core/test/conf/test16.conf | 11 + modules/core/test/conf/test17.conf | 10 + modules/core/test/conf/test18.conf | 10 + modules/core/test/conf/test19.conf | 26 + modules/core/test/conf/test20.conf | 11 + modules/core/test/conf/test21.conf | 11 + modules/core/test/conf/test22.conf | 11 + modules/core/test/conf/test23.conf | 15 + modules/core/test/conf/test24.conf | 23 + modules/core/test/conf/test25.conf | 27 + modules/core/test/conf/test26.conf | 19 + modules/core/test/conf/test27.conf | 22 + modules/core/test/conf/test28.conf | 13 + modules/core/test/conf/test29.conf | 10 + modules/core/test/conf/test30.conf | 12 + modules/core/test/conf/test31.conf | 16 + modules/core/test/conf/test32.conf | 7 + modules/core/test/conf/test33.conf | 3 + modules/core/test/conf/test34.conf | 14 + modules/core/test/conf/test35.conf | 10 + modules/core/test/conf/test36.conf | 12 + modules/core/test/conf/test37.conf | 7 + modules/core/test/conf/test38.conf | 10 + modules/core/test/conf/test39.conf | 23 + modules/core/test/conf/test40.conf | 33 ++ modules/core/test/conf/test41.conf | 20 + modules/core/test/conf/test42.conf | 13 + modules/core/test/conf/test43.conf | 29 ++ modules/core/test/conf/test44.conf | 19 + modules/core/test/conf/test45.conf | 7 + modules/core/test/conf/test46.conf | 11 + modules/core/test/conf/test47.conf | 15 + modules/core/test/conf/test48.conf | 23 + modules/core/test/conf/test49.conf | 2 + modules/core/test/conf/test50.conf | 5 + modules/core/test/conf/test51.conf | 9 + modules/core/test/conf/test52.conf | 8 + modules/core/test/conf/test53.conf | 2 + modules/core/test/conf/test54.conf | 6 + modules/core/test/conf/test55.conf | 11 + modules/core/test/conf/test56.conf | 18 + modules/core/test/conf/test57.conf | 4 + modules/core/test/conf/test58.conf | 4 + modules/core/test/conf/test59.conf | 4 + modules/core/test/conf/test60.conf | 17 + modules/core/test/conf/test61.conf | 18 + modules/core/test/conf/test62.conf | 25 + modules/core/test/conf/test63.conf | 9 + modules/core/test/conf/test64.conf | 5 + modules/core/test/conf/test65.conf | 11 + modules/core/test/conf/test66.conf | 7 + modules/core/test/conf/test67.conf | 1 + modules/core/test/conf/test68.conf | 5 + modules/core/test/conf/test69.conf | 14 + modules/core/test/ref/test01.out | 3 + modules/core/test/ref/test02.out | 3 + modules/core/test/ref/test03.out | 3 + modules/core/test/ref/test04.out | 3 + modules/core/test/ref/test05.out | 3 + modules/core/test/ref/test06.out | 3 + modules/core/test/ref/test07.out | 3 + modules/core/test/ref/test08.out | 3 + modules/core/test/ref/test09.out | 3 + modules/core/test/ref/test10.out | 3 + modules/core/test/ref/test11.out | 6 + modules/core/test/ref/test12.out | 7 + modules/core/test/ref/test13.out | 8 + modules/core/test/ref/test14.out | 14 + modules/core/test/ref/test15.out | 6 + modules/core/test/ref/test16.out | 5 + modules/core/test/ref/test17.out | 7 + modules/core/test/ref/test18.out | 7 + modules/core/test/ref/test19.out | 9 + modules/core/test/ref/test20.out | 4 + modules/core/test/ref/test21.out | 5 + modules/core/test/ref/test22.out | 6 + modules/core/test/ref/test23.out | 7 + modules/core/test/ref/test24.out | 8 + modules/core/test/ref/test25.out | 9 + modules/core/test/ref/test26.out | 11 + modules/core/test/ref/test27.out | 8 + modules/core/test/ref/test28.out | 6 + modules/core/test/ref/test29.out | 4 + modules/core/test/ref/test30.out | 7 + modules/core/test/ref/test31.out | 23 + modules/core/test/ref/test32.out | 3 + modules/core/test/ref/test33.out | 3 + modules/core/test/ref/test34.out | 13 + modules/core/test/ref/test35.out | 13 + modules/core/test/ref/test36.out | 20 + modules/core/test/ref/test37.out | 3 + modules/core/test/ref/test38.out | 6 + modules/core/test/ref/test39.out | 7 + modules/core/test/ref/test40.out | 18 + modules/core/test/ref/test41.out | 9 + modules/core/test/ref/test42.out | 15 + modules/core/test/ref/test43.out | 8 + modules/core/test/ref/test44.out | 5 + modules/core/test/ref/test45.out | 19 + modules/core/test/ref/test46.out | 9 + modules/core/test/ref/test47.out | 8 + modules/core/test/ref/test48.out | 20 + modules/core/test/ref/test49.out | 3 + modules/core/test/ref/test50.out | 3 + modules/core/test/ref/test51.out | 3 + modules/core/test/ref/test52.out | 6 + modules/core/test/ref/test53.out | 3 + modules/core/test/ref/test54.out | 6 + modules/core/test/ref/test55.out | 8 + modules/core/test/ref/test56.out | 12 + modules/core/test/ref/test57.out | 3 + modules/core/test/ref/test58.out | 3 + modules/core/test/ref/test59.out | 3 + modules/core/test/ref/test60.out | 15 + modules/core/test/ref/test61.out | 9 + modules/core/test/ref/test62.out | 15 + modules/core/test/ref/test63.out | 10 + modules/core/test/ref/test64.out | 7 + modules/core/test/ref/test65.out | 7 + modules/core/test/ref/test66.out | 7 + modules/core/test/ref/test67.out | 5 + modules/core/test/ref/test68.out | 6 + modules/core/test/ref/test69.out | 10 + 155 files changed, 5126 insertions(+) create mode 100644 modules/core/Makefile.in create mode 100644 modules/core/NWGNUmakefile create mode 100644 modules/core/config.m4 create mode 100644 modules/core/mod_macro.c create mode 100644 modules/core/mod_macro.dep create mode 100644 modules/core/mod_macro.dsp create mode 100644 modules/core/mod_macro.mak create mode 100644 modules/core/mod_so.c create mode 100644 modules/core/mod_so.h create mode 100644 modules/core/mod_watchdog.c create mode 100644 modules/core/mod_watchdog.dep create mode 100644 modules/core/mod_watchdog.dsp create mode 100644 modules/core/mod_watchdog.h create mode 100644 modules/core/mod_watchdog.mak create mode 100644 modules/core/test/Makefile create mode 100644 modules/core/test/conf/inc63_1.conf create mode 100644 modules/core/test/conf/inc63_2.conf create mode 100644 modules/core/test/conf/test01.conf create mode 100644 modules/core/test/conf/test02.conf create mode 100644 modules/core/test/conf/test03.conf create mode 100644 modules/core/test/conf/test04.conf create mode 100644 modules/core/test/conf/test05.conf create mode 100644 modules/core/test/conf/test06.conf create mode 100644 modules/core/test/conf/test07.conf create mode 100644 modules/core/test/conf/test08.conf create mode 100644 modules/core/test/conf/test09.conf create mode 100644 modules/core/test/conf/test10.conf create mode 100644 modules/core/test/conf/test11.conf create mode 100644 modules/core/test/conf/test12.conf create mode 100644 modules/core/test/conf/test13.conf create mode 100644 modules/core/test/conf/test14.conf create mode 100644 modules/core/test/conf/test15.conf create mode 100644 modules/core/test/conf/test16.conf create mode 100644 modules/core/test/conf/test17.conf create mode 100644 modules/core/test/conf/test18.conf create mode 100644 modules/core/test/conf/test19.conf create mode 100644 modules/core/test/conf/test20.conf create mode 100644 modules/core/test/conf/test21.conf create mode 100644 modules/core/test/conf/test22.conf create mode 100644 modules/core/test/conf/test23.conf create mode 100644 modules/core/test/conf/test24.conf create mode 100644 modules/core/test/conf/test25.conf create mode 100644 modules/core/test/conf/test26.conf create mode 100644 modules/core/test/conf/test27.conf create mode 100644 modules/core/test/conf/test28.conf create mode 100644 modules/core/test/conf/test29.conf create mode 100644 modules/core/test/conf/test30.conf create mode 100644 modules/core/test/conf/test31.conf create mode 100644 modules/core/test/conf/test32.conf create mode 100644 modules/core/test/conf/test33.conf create mode 100644 modules/core/test/conf/test34.conf create mode 100644 modules/core/test/conf/test35.conf create mode 100644 modules/core/test/conf/test36.conf create mode 100644 modules/core/test/conf/test37.conf create mode 100644 modules/core/test/conf/test38.conf create mode 100644 modules/core/test/conf/test39.conf create mode 100644 modules/core/test/conf/test40.conf create mode 100644 modules/core/test/conf/test41.conf create mode 100644 modules/core/test/conf/test42.conf create mode 100644 modules/core/test/conf/test43.conf create mode 100644 modules/core/test/conf/test44.conf create mode 100644 modules/core/test/conf/test45.conf create mode 100644 modules/core/test/conf/test46.conf create mode 100644 modules/core/test/conf/test47.conf create mode 100644 modules/core/test/conf/test48.conf create mode 100644 modules/core/test/conf/test49.conf create mode 100644 modules/core/test/conf/test50.conf create mode 100644 modules/core/test/conf/test51.conf create mode 100644 modules/core/test/conf/test52.conf create mode 100644 modules/core/test/conf/test53.conf create mode 100644 modules/core/test/conf/test54.conf create mode 100644 modules/core/test/conf/test55.conf create mode 100644 modules/core/test/conf/test56.conf create mode 100644 modules/core/test/conf/test57.conf create mode 100644 modules/core/test/conf/test58.conf create mode 100644 modules/core/test/conf/test59.conf create mode 100644 modules/core/test/conf/test60.conf create mode 100644 modules/core/test/conf/test61.conf create mode 100644 modules/core/test/conf/test62.conf create mode 100644 modules/core/test/conf/test63.conf create mode 100644 modules/core/test/conf/test64.conf create mode 100644 modules/core/test/conf/test65.conf create mode 100644 modules/core/test/conf/test66.conf create mode 100644 modules/core/test/conf/test67.conf create mode 100644 modules/core/test/conf/test68.conf create mode 100644 modules/core/test/conf/test69.conf create mode 100644 modules/core/test/ref/test01.out create mode 100644 modules/core/test/ref/test02.out create mode 100644 modules/core/test/ref/test03.out create mode 100644 modules/core/test/ref/test04.out create mode 100644 modules/core/test/ref/test05.out create mode 100644 modules/core/test/ref/test06.out create mode 100644 modules/core/test/ref/test07.out create mode 100644 modules/core/test/ref/test08.out create mode 100644 modules/core/test/ref/test09.out create mode 100644 modules/core/test/ref/test10.out create mode 100644 modules/core/test/ref/test11.out create mode 100644 modules/core/test/ref/test12.out create mode 100644 modules/core/test/ref/test13.out create mode 100644 modules/core/test/ref/test14.out create mode 100644 modules/core/test/ref/test15.out create mode 100644 modules/core/test/ref/test16.out create mode 100644 modules/core/test/ref/test17.out create mode 100644 modules/core/test/ref/test18.out create mode 100644 modules/core/test/ref/test19.out create mode 100644 modules/core/test/ref/test20.out create mode 100644 modules/core/test/ref/test21.out create mode 100644 modules/core/test/ref/test22.out create mode 100644 modules/core/test/ref/test23.out create mode 100644 modules/core/test/ref/test24.out create mode 100644 modules/core/test/ref/test25.out create mode 100644 modules/core/test/ref/test26.out create mode 100644 modules/core/test/ref/test27.out create mode 100644 modules/core/test/ref/test28.out create mode 100644 modules/core/test/ref/test29.out create mode 100644 modules/core/test/ref/test30.out create mode 100644 modules/core/test/ref/test31.out create mode 100644 modules/core/test/ref/test32.out create mode 100644 modules/core/test/ref/test33.out create mode 100644 modules/core/test/ref/test34.out create mode 100644 modules/core/test/ref/test35.out create mode 100644 modules/core/test/ref/test36.out create mode 100644 modules/core/test/ref/test37.out create mode 100644 modules/core/test/ref/test38.out create mode 100644 modules/core/test/ref/test39.out create mode 100644 modules/core/test/ref/test40.out create mode 100644 modules/core/test/ref/test41.out create mode 100644 modules/core/test/ref/test42.out create mode 100644 modules/core/test/ref/test43.out create mode 100644 modules/core/test/ref/test44.out create mode 100644 modules/core/test/ref/test45.out create mode 100644 modules/core/test/ref/test46.out create mode 100644 modules/core/test/ref/test47.out create mode 100644 modules/core/test/ref/test48.out create mode 100644 modules/core/test/ref/test49.out create mode 100644 modules/core/test/ref/test50.out create mode 100644 modules/core/test/ref/test51.out create mode 100644 modules/core/test/ref/test52.out create mode 100644 modules/core/test/ref/test53.out create mode 100644 modules/core/test/ref/test54.out create mode 100644 modules/core/test/ref/test55.out create mode 100644 modules/core/test/ref/test56.out create mode 100644 modules/core/test/ref/test57.out create mode 100644 modules/core/test/ref/test58.out create mode 100644 modules/core/test/ref/test59.out create mode 100644 modules/core/test/ref/test60.out create mode 100644 modules/core/test/ref/test61.out create mode 100644 modules/core/test/ref/test62.out create mode 100644 modules/core/test/ref/test63.out create mode 100644 modules/core/test/ref/test64.out create mode 100644 modules/core/test/ref/test65.out create mode 100644 modules/core/test/ref/test66.out create mode 100644 modules/core/test/ref/test67.out create mode 100644 modules/core/test/ref/test68.out create mode 100644 modules/core/test/ref/test69.out (limited to 'modules/core') diff --git a/modules/core/Makefile.in b/modules/core/Makefile.in new file mode 100644 index 0000000..167b343 --- /dev/null +++ b/modules/core/Makefile.in @@ -0,0 +1,3 @@ + +include $(top_srcdir)/build/special.mk + diff --git a/modules/core/NWGNUmakefile b/modules/core/NWGNUmakefile new file mode 100644 index 0000000..a4dd8d3 --- /dev/null +++ b/modules/core/NWGNUmakefile @@ -0,0 +1,257 @@ +# +# 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 += \ + $(APR)/include \ + $(APRUTIL)/include \ + $(SRC)/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 = macro + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache $(VERSION_STR) Macro Module + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = Echo 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 = + +# +# 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)/macro.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_macro.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 = \ + $(PRELUDE) \ + $(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 = \ + @aprlib.imp \ + @httpd.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + macro_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 + $(call COPY,$(OBJDIR)/*.nlm, $(INSTALLBASE)/modules/) + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APBUILD)/NWGNUtail.inc + + diff --git a/modules/core/config.m4 b/modules/core/config.m4 new file mode 100644 index 0000000..94fb4a1 --- /dev/null +++ b/modules/core/config.m4 @@ -0,0 +1,60 @@ +dnl modules enabled in this directory by default + +dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]]) + +APACHE_MODPATH_INIT(core) + +APR_CHECK_APR_DEFINE(APR_HAS_DSO) + +case "x$enable_so" in + "xyes") + if test $ac_cv_define_APR_HAS_DSO = "no"; then + AC_MSG_ERROR([mod_so has been requested but cannot be built on your system]) + fi + ;; + "xshared") + AC_MSG_ERROR([mod_so can not be built as a shared DSO]) + ;; + "xno") + ;; + "x") + enable_so=$ac_cv_define_APR_HAS_DSO + ;; +esac + +dnl mod_so can only be built statically. Override the default here. +if test "x$enable_so" = "xyes"; then + enable_so="static" +fi + +if test "x$enable_so" = "xstatic"; then + APR_ADDTO(HTTPD_LDFLAGS, [-export-dynamic]) + INSTALL_DSO=yes +else + INSTALL_DSO=no +fi +APACHE_SUBST(INSTALL_DSO) + +if test "$sharedobjs" = "yes"; then + if test $ac_cv_define_APR_HAS_DSO = "no"; then + AC_MSG_ERROR([shared objects have been requested but cannot be built since mod_so cannot be built]) + elif test $enable_so = "no"; then + AC_MSG_ERROR([shared objects have been requested but cannot be built since mod_so was disabled]) + fi +fi + +APACHE_MODULE(so, DSO capability. This module will be automatically enabled unless you build all modules statically., , , $enable_so) + +APACHE_MODULE(watchdog, Watchdog module, , , most, [ + APR_CHECK_APR_DEFINE(APR_HAS_THREADS) + if test $ac_cv_define_APR_HAS_THREADS = "no"; then + AC_MSG_WARN([mod_watchdog requires apr to be built with --enable-threads]) + enable_watchdog=no + fi +]) + +APACHE_MODULE(macro, Define and use macros in configuration files, , , most) + +APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current]) + +APACHE_MODPATH_FINISH diff --git a/modules/core/mod_macro.c b/modules/core/mod_macro.c new file mode 100644 index 0000000..04af43b --- /dev/null +++ b/modules/core/mod_macro.c @@ -0,0 +1,950 @@ +/* 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 "httpd.h" +#include "http_config.h" +#include "http_log.h" + +#include "apr.h" +#include "apr_strings.h" +#include "apr_hash.h" + +/************************************************ COMPILE TIME DEBUG CONTROL */ +/* + debug: + #define MOD_MACRO_DEBUG 1 + + gdb: + run -f ./test/conf/test??.conf +*/ +/* #define MOD_MACRO_DEBUG 1 */ +#undef MOD_MACRO_DEBUG + +#if defined(debug) +#undef debug +#endif /* debug */ + +#if defined(MOD_MACRO_DEBUG) +#define debug(stmt) stmt +#else +#define debug(stmt) +#endif /* MOD_MACRO_DEBUG */ + +/******************************************************** MODULE DECLARATION */ + +module AP_MODULE_DECLARE_DATA macro_module; + +/********************************************************** MACRO MANAGEMENT */ + +/* + this is a macro: name, arguments, contents, location. +*/ +typedef struct +{ + char *name; /* lower case name of the macro */ + apr_array_header_t *arguments; /* of char*, macro parameter names */ + apr_array_header_t *contents; /* of char*, macro body */ + char *location; /* of macro definition, for error messages */ +} ap_macro_t; + +/* configuration tokens. + */ +#define BEGIN_MACRO "" +#define USE_MACRO "Use" +#define UNDEF_MACRO "UndefMacro" + +/* + Macros are kept globally... + They are not per-server or per-directory entities. + + note: they are in a temp_pool, and there is a lazy initialization. + ap_macros is reset to NULL in pre_config hook to not depend + on static vs dynamic configuration. + + hash type: (char *) name -> (ap_macro_t *) macro +*/ +static apr_hash_t *ap_macros = NULL; + +/*************************************************************** PARSE UTILS */ + +#define empty_string_p(p) (!(p) || *(p) == '\0') +#define trim(line) while (*(line) == ' ' || *(line) == '\t') (line)++ + +/* + return configuration-parsed arguments from line as an array. + the line is expected not to contain any '\n'? +*/ +static apr_array_header_t *get_arguments(apr_pool_t * pool, const char *line) +{ + apr_array_header_t *args = apr_array_make(pool, 1, sizeof(char *)); + + trim(line); + while (*line) { + char *arg = ap_getword_conf(pool, &line); + char **new = apr_array_push(args); + *new = arg; + trim(line); + } + + return args; +} + +/* + warn if anything non blank appears, but ignore comments... +*/ +static void warn_if_non_blank(const char * what, + char * ptr, + ap_configfile_t * cfg) +{ + char * p; + for (p=ptr; *p; p++) { + if (*p == '#') + break; + if (*p != ' ' && *p != '\t') { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02989) + "%s on line %d of %s: %s", + what, cfg->line_number, cfg->name, ptr); + break; + } + } +} + +/* + get read lines as an array till end_token. + counts nesting for begin_token/end_token. + it assumes a line-per-line configuration (thru getline). + this function could be exported. + begin_token may be NULL. +*/ +static char *get_lines_till_end_token(apr_pool_t * pool, + ap_configfile_t * config_file, + const char *end_token, + const char *begin_token, + const char *where, + apr_array_header_t ** plines) +{ + apr_array_header_t *lines = apr_array_make(pool, 1, sizeof(char *)); + char line[MAX_STRING_LEN]; /* sorry, but this is expected by getline:-( */ + int macro_nesting = 1, any_nesting = 1; + int line_number_start = config_file->line_number; + + while (!ap_cfg_getline(line, MAX_STRING_LEN, config_file)) { + char *ptr = line; + char *first, **new; + /* skip comments */ + if (*line == '#') + continue; + first = ap_getword_conf_nc(pool, &ptr); + if (first) { + /* detect nesting... */ + if (!strncmp(first, "line_number - line_number_start, + where); + } + } + else if (!strncmp(first, "<", 1)) { + any_nesting++; + } + + if (!strcasecmp(first, end_token)) { + /* check for proper closing */ + char * endp = (char *) ap_strrchr_c(line, '>'); + + /* this cannot happen if end_token contains '>' */ + if (endp == NULL) { + return "end directive missing closing '>'"; + } + + warn_if_non_blank( + APLOGNO(02794) "non blank chars found after directive closing", + endp+1, config_file); + + macro_nesting--; + if (!macro_nesting) { + if (any_nesting) { + ap_log_error(APLOG_MARK, + APLOG_WARNING, 0, NULL, APLOGNO(02795) + "bad cumulated nesting (%+d) in %s", + any_nesting, where); + } + *plines = lines; + return NULL; + } + } + else if (begin_token && !strcasecmp(first, begin_token)) { + macro_nesting++; + } + } + new = apr_array_push(lines); + *new = apr_psprintf(pool, "%s" APR_EOL_STR, line); /* put EOL back? */ + } + + return apr_psprintf(pool, "expected token not found: %s", end_token); +} + +/* the @* arguments are double-quote escaped when substituted */ +#define ESCAPE_ARG '@' + +/* other $* and %* arguments are simply replaced without escaping */ +#define ARG_PREFIX "$%@" + +/* + characters allowed in an argument? + not used yet, because that would trigger some backward compatibility. +*/ +#define ARG_CONTENT \ + "abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "0123456789_" ARG_PREFIX + +/* + returns whether it looks like an argument, i.e. prefixed by ARG_PREFIX. +*/ +static int looks_like_an_argument(const char *word) +{ + return ap_strchr(ARG_PREFIX, *word) != 0; +} + +/* + generates an error on macro with two arguments of the same name. + generates an error if a macro argument name is empty. + generates a warning if arguments name prefixes conflict. + generates a warning if the first char of an argument is not in ARG_PREFIX +*/ +static const char *check_macro_arguments(apr_pool_t * pool, + const ap_macro_t * macro) +{ + char **tab = (char **) macro->arguments->elts; + int nelts = macro->arguments->nelts; + int i; + + for (i = 0; i < nelts; i++) { + size_t ltabi = strlen(tab[i]); + int j; + + if (ltabi == 0) { + return apr_psprintf(pool, + "macro '%s' (%s): empty argument #%d name", + macro->name, macro->location, i + 1); + } + else if (!looks_like_an_argument(tab[i])) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02796) + "macro '%s' (%s) " + "argument name '%s' (#%d) without expected prefix, " + "better prefix argument names with one of '%s'.", + macro->name, macro->location, + tab[i], i + 1, ARG_PREFIX); + } + + for (j = i + 1; j < nelts; j++) { + size_t ltabj = strlen(tab[j]); + + /* must not use the same argument name twice */ + if (!strcmp(tab[i], tab[j])) { + return apr_psprintf(pool, + "argument name conflict in macro '%s' (%s): " + "argument '%s': #%d and #%d, " + "change argument names!", + macro->name, macro->location, + tab[i], i + 1, j + 1); + } + + /* warn about common prefix, but only if non empty names */ + if (ltabi && ltabj && + !strncmp(tab[i], tab[j], ltabi < ltabj ? ltabi : ltabj)) { + ap_log_error(APLOG_MARK, APLOG_WARNING, + 0, NULL, APLOGNO(02797) + "macro '%s' (%s): " + "argument name prefix conflict (%s #%d and %s #%d), " + "be careful about your macro definition!", + macro->name, macro->location, + tab[i], i + 1, tab[j], j + 1); + } + } + } + + return NULL; +} + +/* + warn about empty strings in array. could be legitimate. +*/ +static void check_macro_use_arguments(const char *where, + const apr_array_header_t * array) +{ + char **tab = (char **) array->elts; + int i; + for (i = 0; i < array->nelts; i++) { + if (empty_string_p(tab[i])) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02798) + "%s: empty argument #%d", where, i + 1); + } + } +} + +/******************************************************** SUBSTITUTION UTILS */ + +/* could be switched to '\'' */ +#define DELIM '"' +#define ESCAPE '\\' + +/* + returns the number of needed escapes for the string +*/ +static int number_of_escapes(const char delim, const char *str) +{ + int nesc = 0; + const char *s = str; + while (*s) { + if (*s == ESCAPE || *s == delim) + nesc++; + s++; + } + debug(fprintf(stderr, "escapes: %d ---%s---\n", nesc, str)); + return nesc; +} + +/* + replace name by replacement at the beginning of buf of bufsize. + returns an error message or NULL. + C is not really a nice language for processing strings. +*/ +static char *substitute(char *buf, + const int bufsize, + const char *name, + const char *replacement, const int do_esc) +{ + int lbuf = strlen(buf), + lname = strlen(name), + lrepl = strlen(replacement), + lsubs = lrepl + + (do_esc ? (2 + number_of_escapes(DELIM, replacement)) : 0), + shift = lsubs - lname, size = lbuf + shift, i, j; + + /* buf must starts with name */ + ap_assert(!strncmp(buf, name, lname)); + + /* hmmm??? */ + if (!strcmp(name, replacement)) + return NULL; + + debug(fprintf(stderr, + "substitute(%s,%s,%s,%d,sh=%d,lbuf=%d,lrepl=%d,lsubs=%d)\n", + buf, name, replacement, do_esc, shift, lbuf, lrepl, lsubs)); + + if (size >= bufsize) { + /* could/should I reallocate? */ + return "cannot substitute, buffer size too small"; + } + + /* cannot use strcpy as strings may overlap */ + if (shift != 0) { + memmove(buf + lname + shift, buf + lname, lbuf - lname + 1); + } + + /* insert the replacement with escapes */ + j = 0; + if (do_esc) + buf[j++] = DELIM; + for (i = 0; i < lrepl; i++, j++) { + if (do_esc && (replacement[i] == DELIM || replacement[i] == ESCAPE)) + buf[j++] = ESCAPE; + buf[j] = replacement[i]; + } + if (do_esc) + buf[j++] = DELIM; + + return NULL; +} + +/* + find first occurrence of args in buf. + in case of conflict, the LONGEST argument is kept. (could be the FIRST?). + returns the pointer and the whichone found, or NULL. +*/ +static char *next_substitution(const char *buf, + const apr_array_header_t * args, int *whichone) +{ + char *chosen = NULL, **tab = (char **) args->elts; + size_t lchosen = 0; + int i; + + for (i = 0; i < args->nelts; i++) { + char *found = ap_strstr((char *) buf, tab[i]); + size_t lfound = strlen(tab[i]); + if (found && (!chosen || found < chosen || + (found == chosen && lchosen < lfound))) { + chosen = found; + lchosen = lfound; + *whichone = i; + } + } + + return chosen; +} + +/* + substitute macro arguments by replacements in buf of bufsize. + returns an error message or NULL. + if used is defined, returns the used macro arguments. +*/ +static const char *substitute_macro_args( + char *buf, + int bufsize, + const ap_macro_t * macro, + const apr_array_header_t * replacements, + apr_array_header_t * used) +{ + char *ptr = buf, + **atab = (char **) macro->arguments->elts, + **rtab = (char **) replacements->elts; + int whichone = -1; + + if (used) { + ap_assert(used->nalloc >= replacements->nelts); + } + debug(fprintf(stderr, "1# %s", buf)); + + while ((ptr = next_substitution(ptr, macro->arguments, &whichone))) { + const char *errmsg = substitute(ptr, buf - ptr + bufsize, + atab[whichone], rtab[whichone], + atab[whichone][0] == ESCAPE_ARG); + if (errmsg) { + return errmsg; + } + ptr += strlen(rtab[whichone]); + if (used) { + used->elts[whichone] = 1; + } + } + debug(fprintf(stderr, "2# %s", buf)); + + return NULL; +} + +/* + perform substitutions in a macro contents and + return the result as a newly allocated array, if result is defined. + may also return an error message. + passes used down to substitute_macro_args. +*/ +static const char *process_content(apr_pool_t * pool, + const ap_macro_t * macro, + const apr_array_header_t * replacements, + apr_array_header_t * used, + apr_array_header_t ** result) +{ + apr_array_header_t *contents = macro->contents; + char line[MAX_STRING_LEN]; + int i; + + if (result) { + *result = apr_array_make(pool, contents->nelts, sizeof(char *)); + } + + /* for each line of the macro body */ + for (i = 0; i < contents->nelts; i++) { + const char *errmsg; + /* copy the line and substitute macro parameters */ + strncpy(line, ((char **) contents->elts)[i], MAX_STRING_LEN - 1); + errmsg = substitute_macro_args(line, MAX_STRING_LEN, + macro, replacements, used); + if (errmsg) { + return apr_psprintf(pool, + "while processing line %d of macro '%s' (%s) %s", + i + 1, macro->name, macro->location, errmsg); + } + /* append substituted line to result array */ + if (result) { + char **new = apr_array_push(*result); + *new = apr_pstrdup(pool, line); + } + } + + return NULL; +} + +/* + warn if some macro arguments are not used. +*/ +static const char *check_macro_contents(apr_pool_t * pool, + const ap_macro_t * macro) +{ + int nelts = macro->arguments->nelts; + char **names = (char **) macro->arguments->elts; + apr_array_header_t *used; + int i; + const char *errmsg; + + if (macro->contents->nelts == 0) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02799) + "macro '%s' (%s): empty contents!", + macro->name, macro->location); + return NULL; /* no need to further warnings... */ + } + + used = apr_array_make(pool, nelts, sizeof(char)); + + for (i = 0; i < nelts; i++) { + used->elts[i] = 0; + } + + errmsg = process_content(pool, macro, macro->arguments, used, NULL); + + if (errmsg) { + return errmsg; + } + + for (i = 0; i < nelts; i++) { + if (!used->elts[i]) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02800) + "macro '%s' (%s): argument '%s' (#%d) never used", + macro->name, macro->location, names[i], i + 1); + } + } + + return NULL; +} + + +/************************************************** MACRO PSEUDO CONFIG FILE */ + +/* + The expanded content of the macro is to be parsed as a ap_configfile_t. + This is used to have some kind of old fashionned C object oriented inherited + data structure for configs. + + The following struct stores the contents. + + This structure holds pointers (next, upper) to the current "file" which was + being processed and is interrupted by the macro expansion. At the end + of processing the macro, the initial data structure will be put back + in place (see function next_one) and the reading will go on from there. + + If macros are used within macros, there may be a cascade of such temporary + arrays used to insert the expanded macro contents before resuming the real + file processing. + + There is some hopus-pocus to deal with line_number when transiting from + one config to the other. +*/ +typedef struct +{ + int index; /* current element */ + int char_index; /* current char in element */ + int length; /* cached length of the current line */ + apr_array_header_t *contents; /* array of char * */ + ap_configfile_t *next; /* next config once this one is processed */ + ap_configfile_t **upper; /* hack: where to update it if needed */ +} array_contents_t; + +/* + Get next config if any. + this may be called several times if there are continuations. +*/ +static int next_one(array_contents_t * ml) +{ + if (ml->next) { + ap_assert(ml->upper); + *(ml->upper) = ml->next; + return 1; + } + return 0; +} + +/* + returns next char if possible + this may involve switching to enclosing config. +*/ +static apr_status_t array_getch(char *ch, void *param) +{ + array_contents_t *ml = (array_contents_t *) param; + char **tab = (char **) ml->contents->elts; + + while (ml->char_index >= ml->length) { + if (ml->index >= ml->contents->nelts) { + /* maybe update */ + if (ml->next && ml->next->getch && next_one(ml)) { + apr_status_t rc = ml->next->getch(ch, ml->next->param); + if (*ch==LF) + ml->next->line_number++; + return rc; + } + return APR_EOF; + } + ml->index++; + ml->char_index = 0; + ml->length = ml->index >= ml->contents->nelts ? + 0 : strlen(tab[ml->index]); + } + + *ch = tab[ml->index][ml->char_index++]; + return APR_SUCCESS; +} + +/* + returns a buf a la fgets. + no more than a line at a time, otherwise the parsing is too much ahead... + NULL at EOF. +*/ +static apr_status_t array_getstr(void *buf, size_t bufsize, void *param) +{ + array_contents_t *ml = (array_contents_t *) param; + char *buffer = (char *) buf; + char next = '\0'; + size_t i = 0; + apr_status_t rc = APR_SUCCESS; + + /* read chars from stream, stop on newline */ + while (i < bufsize - 1 && next != LF && + ((rc = array_getch(&next, param)) == APR_SUCCESS)) { + buffer[i++] = next; + } + + if (rc == APR_EOF) { + /* maybe update to next, possibly a recursion */ + if (next_one(ml)) { + ap_assert(ml->next->getstr); + /* keep next line count in sync! the caller will update + the current line_number, we need to forward to the next */ + ml->next->line_number++; + return ml->next->getstr(buf, bufsize, ml->next->param); + } + /* else that is really all we can do */ + return APR_EOF; + } + + buffer[i] = '\0'; + + return APR_SUCCESS; +} + +/* + close the array stream? +*/ +static apr_status_t array_close(void *param) +{ + array_contents_t *ml = (array_contents_t *) param; + /* move index at end of stream... */ + ml->index = ml->contents->nelts; + ml->char_index = ml->length; + return APR_SUCCESS; +} + +/* + create an array config stream insertion "object". + could be exported. +*/ +static ap_configfile_t *make_array_config(apr_pool_t * pool, + apr_array_header_t * contents, + const char *where, + ap_configfile_t * cfg, + ap_configfile_t ** upper) +{ + array_contents_t *ls = + (array_contents_t *) apr_palloc(pool, sizeof(array_contents_t)); + ap_assert(ls!=NULL); + + ls->index = 0; + ls->char_index = 0; + ls->contents = contents; + ls->length = ls->contents->nelts < 1 ? + 0 : strlen(((char **) ls->contents->elts)[0]); + ls->next = cfg; + ls->upper = upper; + + return ap_pcfg_open_custom(pool, where, (void *) ls, + array_getch, array_getstr, array_close); +} + + +/********************************************************** KEYWORD HANDLING */ + +/* + handles: any trash there is ignored... +*/ +static const char *macro_section(cmd_parms * cmd, + void *dummy, const char *arg) +{ + apr_pool_t *pool; + char *endp, *name, *where; + const char *errmsg; + ap_macro_t *macro; + + debug(fprintf(stderr, "macro_section: arg='%s'\n", arg)); + + /* lazy initialization */ + if (ap_macros == NULL) { + pool = cmd->pool; + ap_macros = apr_hash_make(pool); + ap_assert(ap_macros != NULL); + apr_pool_cleanup_register(pool, &ap_macros, + ap_pool_cleanup_set_null, + apr_pool_cleanup_null); + } + else { + pool = apr_hash_pool_get(ap_macros); + } + + endp = (char *) ap_strrchr_c(arg, '>'); + + if (endp == NULL) { + return BEGIN_MACRO "> directive missing closing '>'"; + } + + if (endp == arg) { + return BEGIN_MACRO " macro definition: empty name"; + } + + warn_if_non_blank(APLOGNO(02801) "non blank chars found after " + BEGIN_MACRO " closing '>'", + endp+1, cmd->config_file); + + /* coldly drop '>[^>]*$' out */ + *endp = '\0'; + + /* get lowercase macro name */ + name = ap_getword_conf(pool, &arg); + if (empty_string_p(name)) { + return BEGIN_MACRO " macro definition: name not found"; + } + + ap_str_tolower(name); + macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING); + + if (macro != NULL) { + /* already defined: warn about the redefinition */ + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02802) + "macro '%s' multiply defined: " + "%s, redefined on line %d of \"%s\"", + macro->name, macro->location, + cmd->config_file->line_number, cmd->config_file->name); + } + else { + /* allocate a new macro */ + macro = (ap_macro_t *) apr_palloc(pool, sizeof(ap_macro_t)); + macro->name = name; + } + + debug(fprintf(stderr, "macro_section: name=%s\n", name)); + + /* get macro arguments */ + macro->location = apr_psprintf(pool, + "defined on line %d of \"%s\"", + cmd->config_file->line_number, + cmd->config_file->name); + debug(fprintf(stderr, "macro_section: location=%s\n", macro->location)); + + where = + apr_psprintf(pool, "macro '%s' (%s)", macro->name, macro->location); + + if (looks_like_an_argument(name)) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02803) + "%s better prefix a macro name with any of '%s'", + where, ARG_PREFIX); + } + + /* get macro parameters */ + macro->arguments = get_arguments(pool, arg); + + errmsg = check_macro_arguments(cmd->temp_pool, macro); + + if (errmsg) { + return errmsg; + } + + errmsg = get_lines_till_end_token(pool, cmd->config_file, + END_MACRO, BEGIN_MACRO, + where, ¯o->contents); + + if (errmsg) { + return apr_psprintf(cmd->temp_pool, + "%s" APR_EOL_STR "\tcontents error: %s", + where, errmsg); + } + + errmsg = check_macro_contents(cmd->temp_pool, macro); + + if (errmsg) { + return apr_psprintf(cmd->temp_pool, + "%s" APR_EOL_STR "\tcontents checking error: %s", + where, errmsg); + } + + /* store the new macro */ + apr_hash_set(ap_macros, name, APR_HASH_KEY_STRING, macro); + + return NULL; +} + +/* + handles: Use name value1 value2 ... +*/ +static const char *use_macro(cmd_parms * cmd, void *dummy, const char *arg) +{ + char *name, *recursion, *where; + const char *errmsg; + ap_macro_t *macro; + apr_array_header_t *replacements; + apr_array_header_t *contents; + + debug(fprintf(stderr, "use_macro -%s-\n", arg)); + + /* must be initialized, or no macros has been defined */ + if (ap_macros == NULL) { + return "no macro defined before " USE_MACRO; + } + + /* get lowercase macro name */ + name = ap_getword_conf(cmd->temp_pool, &arg); + ap_str_tolower(name); + + if (empty_string_p(name)) { + return "no macro name specified with " USE_MACRO; + } + + /* get macro definition */ + macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING); + + if (!macro) { + return apr_psprintf(cmd->temp_pool, "macro '%s' undefined", name); + } + + /* recursion is detected here by looking at the config file name, + * which may already contains "macro 'foo'". Ok, it looks like a hack, + * but otherwise it is uneasy to keep this data available somewhere... + * the name has just the needed visibility and liveness. + */ + recursion = + apr_pstrcat(cmd->temp_pool, "macro '", macro->name, "'", NULL); + + if (ap_strstr((char *) cmd->config_file->name, recursion)) { + return apr_psprintf(cmd->temp_pool, + "recursive use of macro '%s' is invalid", + macro->name); + } + + /* get macro arguments */ + replacements = get_arguments(cmd->temp_pool, arg); + + if (macro->arguments->nelts != replacements->nelts) { + return apr_psprintf(cmd->temp_pool, + "macro '%s' (%s) used " + "with %d arguments instead of %d", + macro->name, macro->location, + replacements->nelts, macro->arguments->nelts); + } + + where = apr_psprintf(cmd->temp_pool, + "macro '%s' (%s) used on line %d of \"%s\"", + macro->name, macro->location, + cmd->config_file->line_number, + cmd->config_file->name); + + check_macro_use_arguments(where, replacements); + + errmsg = process_content(cmd->temp_pool, macro, replacements, + NULL, &contents); + + if (errmsg) { + return apr_psprintf(cmd->temp_pool, + "%s error while substituting: %s", + where, errmsg); + } + + /* the current "config file" is replaced by a string array... + at the end of processing the array, the initial config file + will be returned there (see next_one) so as to go on. */ + cmd->config_file = make_array_config(cmd->temp_pool, contents, where, + cmd->config_file, &cmd->config_file); + + return NULL; +} + +static const char *undef_macro(cmd_parms * cmd, void *dummy, const char *arg) +{ + char *name; + ap_macro_t *macro; + + /* must be initialized, or no macros has been defined */ + if (ap_macros == NULL) { + return "no macro defined before " UNDEF_MACRO; + } + + if (empty_string_p(arg)) { + return "no macro name specified with " UNDEF_MACRO; + } + + /* check that the macro is defined */ + name = apr_pstrdup(cmd->temp_pool, arg); + ap_str_tolower(name); + macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING); + if (macro == NULL) { + /* could be a warning? */ + return apr_psprintf(cmd->temp_pool, + "cannot remove undefined macro '%s'", name); + } + + /* free macro: cannot do that */ + /* remove macro from hash table */ + apr_hash_set(ap_macros, name, APR_HASH_KEY_STRING, NULL); + + return NULL; +} + +/************************************************************* EXPORT MODULE */ + +/* + macro module commands. + configuration file macro stuff + they are processed immediately when found, hence the EXEC_ON_READ. +*/ +static const command_rec macro_cmds[] = { + AP_INIT_RAW_ARGS(BEGIN_MACRO, macro_section, NULL, EXEC_ON_READ | OR_ALL, + "Beginning of a macro definition section."), + AP_INIT_RAW_ARGS(USE_MACRO, use_macro, NULL, EXEC_ON_READ | OR_ALL, + "Use of a macro."), + AP_INIT_TAKE1(UNDEF_MACRO, undef_macro, NULL, EXEC_ON_READ | OR_ALL, + "Remove a macro definition."), + + {NULL} +}; + +/* + Module hooks are request-oriented thus it does not suit configuration + file utils a lot. I haven't found any clean hook to apply something + before then after configuration file processing. Also what about + .htaccess files? + + Thus I think that server/util.c or server/config.c + would be a better place for this stuff. +*/ + +AP_DECLARE_MODULE(macro) = { + STANDARD20_MODULE_STUFF, /* common stuff */ + NULL, /* create per-directory config */ + NULL, /* merge per-directory config structures */ + NULL, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + macro_cmds, /* configuration commands */ + NULL /* register hooks */ +}; diff --git a/modules/core/mod_macro.dep b/modules/core/mod_macro.dep new file mode 100644 index 0000000..74ea1a5 --- /dev/null +++ b/modules/core/mod_macro.dep @@ -0,0 +1,45 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_macro.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_macro.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\os.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + diff --git a/modules/core/mod_macro.dsp b/modules/core/mod_macro.dsp new file mode 100644 index 0000000..61914cc --- /dev/null +++ b/modules/core/mod_macro.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_macro" - 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_macro - 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_macro.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_macro.mak" CFG="mod_macro - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_macro - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_macro - 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_macro - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_macro_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" /i "../../include" /i "../../srclib/apr/include" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" +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_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_macro.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_macro - 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_macro_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" /i "../../include" /i "../../srclib/apr/include" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" +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_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_macro.so" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_macro.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_macro - Win32 Release" +# Name "mod_macro - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_macro.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/core/mod_macro.mak b/modules/core/mod_macro.mak new file mode 100644 index 0000000..656d96a --- /dev/null +++ b/modules/core/mod_macro.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_macro.dsp +!IF "$(CFG)" == "" +CFG=mod_macro - Win32 Release +!MESSAGE No configuration specified. Defaulting to mod_macro - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "mod_macro - Win32 Release" && "$(CFG)" != "mod_macro - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_macro.mak" CFG="mod_macro - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_macro - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_macro - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_macro - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\httpd.res" + -@erase "$(INTDIR)\mod_macro.obj" + -@erase "$(INTDIR)\mod_macro_src.idb" + -@erase "$(INTDIR)\mod_macro_src.pdb" + -@erase "$(OUTDIR)\mod_macro.exp" + -@erase "$(OUTDIR)\mod_macro.lib" + -@erase "$(OUTDIR)\mod_macro.pdb" + -@erase "$(OUTDIR)\mod_macro.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_macro_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_macro.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_macro.pdb" /debug /out:"$(OUTDIR)\mod_macro.so" /implib:"$(OUTDIR)\mod_macro.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_macro.obj" \ + "$(INTDIR)\httpd.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_macro.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_macro.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_macro.so" + if exist .\Release\mod_macro.so.manifest mt.exe -manifest .\Release\mod_macro.so.manifest -outputresource:.\Release\mod_macro.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_macro.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\httpd.res" + -@erase "$(INTDIR)\mod_macro.obj" + -@erase "$(INTDIR)\mod_macro_src.idb" + -@erase "$(INTDIR)\mod_macro_src.pdb" + -@erase "$(OUTDIR)\mod_macro.exp" + -@erase "$(OUTDIR)\mod_macro.lib" + -@erase "$(OUTDIR)\mod_macro.pdb" + -@erase "$(OUTDIR)\mod_macro.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_macro_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_macro.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_macro.pdb" /debug /out:"$(OUTDIR)\mod_macro.so" /implib:"$(OUTDIR)\mod_macro.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_macro.so +LINK32_OBJS= \ + "$(INTDIR)\mod_macro.obj" \ + "$(INTDIR)\httpd.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_macro.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_macro.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_macro.so" + if exist .\Debug\mod_macro.so.manifest mt.exe -manifest .\Debug\mod_macro.so.manifest -outputresource:.\Debug\mod_macro.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_macro.dep") +!INCLUDE "mod_macro.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_macro.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_macro - Win32 Release" || "$(CFG)" == "mod_macro - Win32 Debug" + +!IF "$(CFG)" == "mod_macro - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\core" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\core" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ENDIF + +!IF "$(CFG)" == "mod_macro - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\core" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\core" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ENDIF + +!IF "$(CFG)" == "mod_macro - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\core" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\core" + +!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\core" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\core" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_macro - Win32 Release" + + +"$(INTDIR)\httpd.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_macro - Win32 Debug" + + +"$(INTDIR)\httpd.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\httpd.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_macro.so" /d LONG_NAME="macro_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_macro.c + +"$(INTDIR)\mod_macro.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/core/mod_so.c b/modules/core/mod_so.c new file mode 100644 index 0000000..f5d18c1 --- /dev/null +++ b/modules/core/mod_so.c @@ -0,0 +1,442 @@ +/* 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. + */ + +/* + * This module is used to load Apache modules at runtime. This means that the + * server functionality can be extended without recompiling and even without + * taking the server down at all. Only a HUP or AP_SIG_GRACEFUL signal + * needs to be sent to the server to reload the dynamically loaded modules. + * + * To use, you'll first need to build your module as a shared library, then + * update your configuration (httpd.conf) to get the Apache core to load the + * module at start-up. + * + * The easiest way to build a module as a shared library is to use the + * `SharedModule' command in the Configuration file, instead of `AddModule'. + * You should also change the file extension from `.o' to `.so'. So, for + * example, to build the status module as a shared library edit Configuration + * and change + * AddModule modules/standard/mod_status.o + * to + * SharedModule modules/standard/mod_status.so + * + * Run Configure and make. Now Apache's httpd binary will _not_ include + * mod_status. Instead a shared object called mod_status.so will be build, in + * the modules/standard directory. You can build most of the modules as shared + * libraries like this. + * + * To use the shared module, move the .so file(s) into an appropriate + * directory. You might like to create a directory called "modules" under you + * server root for this (e.g. /usr/local/httpd/modules). + * + * Then edit your conf/httpd.conf file, and add LoadModule lines. For + * example + * LoadModule status_module modules/mod_status.so + * + * The first argument is the module's structure name (look at the end of the + * module source to find this). The second option is the path to the module + * file, relative to the server root. Put these directives right at the top + * of your httpd.conf file. + * + * Now you can start Apache. A message will be logged at "debug" level to your + * error_log to confirm that the module(s) are loaded (use "LogLevel debug" + * directive to get these log messages). + * + * If you edit the LoadModule directives while the server is live you can get + * Apache to re-load the modules by sending it a HUP or AP_SIG_GRACEFUL + * signal as normal. You can use this to dynamically change the capability + * of your server without bringing it down. + * + * Because currently there is only limited builtin support in the Configure + * script for creating the shared library files (`.so'), please consult your + * vendors cc(1), ld(1) and dlopen(3) manpages to find out the appropriate + * compiler and linker flags and insert them manually into the Configuration + * file under CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT. + * + * If you still have problems figuring out the flags both try the paper + * http://developer.netscape.com/library/documentation/enterprise + * /unix/svrplug.htm#1013807 + * or install a Perl 5 interpreter on your platform and then run the command + * + * $ perl -V:usedl -V:ccdlflags -V:cccdlflags -V:lddlflags + * + * This gives you what type of dynamic loading Perl 5 uses on your platform + * and which compiler and linker flags Perl 5 uses to create the shared object + * files. + * + * Another location where you can find useful hints is the `ltconfig' script + * of the GNU libtool 1.2 package. Search for your platform name inside the + * various "case" constructs. + * + */ + +#include "apr.h" +#include "apr_dso.h" +#include "apr_strings.h" +#include "apr_errno.h" + +#include "ap_config.h" +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "http_core.h" + +#include "mod_so.h" + +module AP_MODULE_DECLARE_DATA so_module; + + +/* + * Server configuration to keep track of actually + * loaded modules and the corresponding module name. + */ + +typedef struct so_server_conf { + apr_array_header_t *loaded_modules; +} so_server_conf; + +static void *so_sconf_create(apr_pool_t *p, server_rec *s) +{ + so_server_conf *soc; + + soc = (so_server_conf *)apr_pcalloc(p, sizeof(so_server_conf)); + soc->loaded_modules = apr_array_make(p, DYNAMIC_MODULE_LIMIT, + sizeof(ap_module_symbol_t)); + + return (void *)soc; +} + +#ifndef NO_DLOPEN + +/* + * This is the cleanup for a loaded shared object. It unloads the module. + * This is called as a cleanup function from the core. + */ + +static apr_status_t unload_module(void *data) +{ + ap_module_symbol_t *modi = (ap_module_symbol_t*)data; + + /* only unload if module information is still existing */ + if (modi->modp == NULL) + return APR_SUCCESS; + + /* remove the module pointer from the core structure */ + ap_remove_loaded_module(modi->modp); + + /* destroy the module information */ + modi->modp = NULL; + modi->name = NULL; + return APR_SUCCESS; +} + +static const char *dso_load(cmd_parms *cmd, apr_dso_handle_t **modhandlep, + const char *filename, const char **used_filename) +{ + int retry = 0; + const char *fullname = ap_server_root_relative(cmd->temp_pool, filename); + char my_error[256]; + if (filename != NULL && ap_strchr_c(filename, '/') == NULL) { + /* retry on error without path to use dlopen()'s search path */ + retry = 1; + } + + if (fullname == NULL && !retry) { + return apr_psprintf(cmd->temp_pool, "Invalid %s path %s", + cmd->cmd->name, filename); + } + *used_filename = fullname; + if (fullname && apr_dso_load(modhandlep, fullname, cmd->pool) == APR_SUCCESS) { + return NULL; + } + if (retry) { + *used_filename = filename; + if (apr_dso_load(modhandlep, filename, cmd->pool) == APR_SUCCESS) + return NULL; + } + + return apr_pstrcat(cmd->temp_pool, "Cannot load ", filename, + " into server: ", + apr_dso_error(*modhandlep, my_error, sizeof(my_error)), + NULL); +} + +/* + * This is called for the directive LoadModule and actually loads + * a shared object file into the address space of the server process. + */ + +static const char *load_module(cmd_parms *cmd, void *dummy, + const char *modname, const char *filename) +{ + apr_dso_handle_t *modhandle; + apr_dso_handle_sym_t modsym; + module *modp; + const char *module_file; + so_server_conf *sconf; + ap_module_symbol_t *modi; + ap_module_symbol_t *modie; + int i; + const char *error; + + /* we need to setup this value for dummy to make sure that we don't try + * to add a non-existent tree into the build when we return to + * execute_now. + */ + *(ap_directive_t **)dummy = NULL; + + /* + * check for already existing module + * If it already exists, we have nothing to do + * Check both dynamically-loaded modules and statically-linked modules. + */ + sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config, + &so_module); + modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; + for (i = 0; i < sconf->loaded_modules->nelts; i++) { + modi = &modie[i]; + if (modi->name != NULL && strcmp(modi->name, modname) == 0) { + ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, cmd->pool, APLOGNO(01574) + "module %s is already loaded, skipping", + modname); + return NULL; + } + } + + for (i = 0; ap_preloaded_modules[i]; i++) { + const char *preload_name; + apr_size_t preload_len; + apr_size_t thismod_len; + + modp = ap_preloaded_modules[i]; + + /* make sure we're comparing apples with apples + * make sure name of preloaded module is mod_FOO.c + * make sure name of structure being loaded is FOO_module + */ + + if (memcmp(modp->name, "mod_", 4)) { + continue; + } + + preload_name = modp->name + strlen("mod_"); + preload_len = strlen(preload_name) - 2; + + if (strlen(modname) <= strlen("_module")) { + continue; + } + thismod_len = strlen(modname) - strlen("_module"); + if (strcmp(modname + thismod_len, "_module")) { + continue; + } + + if (thismod_len != preload_len) { + continue; + } + + if (!memcmp(modname, preload_name, preload_len)) { + return apr_pstrcat(cmd->pool, "module ", modname, + " is built-in and can't be loaded", + NULL); + } + } + + modi = apr_array_push(sconf->loaded_modules); + modi->name = modname; + + /* + * Load the file into the Apache address space + */ + error = dso_load(cmd, &modhandle, filename, &module_file); + if (error) + return error; + ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool, APLOGNO(01575) + "loaded module %s from %s", modname, module_file); + + /* + * Retrieve the pointer to the module structure through the module name: + * First with the hidden variant (prefix `AP_') and then with the plain + * symbol name. + */ + if (apr_dso_sym(&modsym, modhandle, modname) != APR_SUCCESS) { + char my_error[256]; + + return apr_pstrcat(cmd->pool, "Can't locate API module structure `", + modname, "' in file ", module_file, ": ", + apr_dso_error(modhandle, my_error, sizeof(my_error)), + NULL); + } + modp = (module*) modsym; + modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle; + modi->modp = modp; + + /* + * Make sure the found module structure is really a module structure + * + */ + if (modp->magic != MODULE_MAGIC_COOKIE) { + return apr_psprintf(cmd->pool, "API module structure '%s' in file %s " + "is garbled - expected signature %08lx but saw " + "%08lx - perhaps this is not an Apache module DSO, " + "or was compiled for a different Apache version?", + modname, module_file, + MODULE_MAGIC_COOKIE, modp->magic); + } + + /* + * Add this module to the Apache core structures + */ + error = ap_add_loaded_module(modp, cmd->pool, modname); + if (error) { + return error; + } + + /* + * Register a cleanup in the config apr_pool_t (normally pconf). When + * we do a restart (or shutdown) this cleanup will cause the + * shared object to be unloaded. + */ + apr_pool_cleanup_register(cmd->pool, modi, unload_module, apr_pool_cleanup_null); + + /* + * Finally we need to run the configuration process for the module + */ + ap_single_module_configure(cmd->pool, cmd->server, modp); + + return NULL; +} + +/* + * This implements the LoadFile directive and loads an arbitrary + * shared object file into the address space of the server process. + */ + +static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename) +{ + apr_dso_handle_t *handle; + const char *used_file, *error; + + error = dso_load(cmd, &handle, filename, &used_file); + if (error) + return error; + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01576) + "loaded file %s", used_file); + + return NULL; +} + +static module *ap_find_loaded_module_symbol(server_rec *s, const char *modname) +{ + so_server_conf *sconf; + ap_module_symbol_t *modi; + ap_module_symbol_t *modie; + int i; + + sconf = (so_server_conf *)ap_get_module_config(s->module_config, + &so_module); + modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; + + for (i = 0; i < sconf->loaded_modules->nelts; i++) { + modi = &modie[i]; + if (modi->name != NULL && strcmp(modi->name, modname) == 0) { + return modi->modp; + } + } + return NULL; +} + +static void dump_loaded_modules(apr_pool_t *p, server_rec *s) +{ + ap_module_symbol_t *modie; + ap_module_symbol_t *modi; + so_server_conf *sconf; + int i; + apr_file_t *out = NULL; + + if (!ap_exists_config_define("DUMP_MODULES")) { + return; + } + + apr_file_open_stdout(&out, p); + + apr_file_printf(out, "Loaded Modules:\n"); + + sconf = (so_server_conf *)ap_get_module_config(s->module_config, + &so_module); + for (i = 0; ; i++) { + modi = &ap_prelinked_module_symbols[i]; + if (modi->name != NULL) { + apr_file_printf(out, " %s (static)\n", modi->name); + } + else { + break; + } + } + + modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; + for (i = 0; i < sconf->loaded_modules->nelts; i++) { + modi = &modie[i]; + if (modi->name != NULL) { + apr_file_printf(out, " %s (shared)\n", modi->name); + } + } +} + +#else /* not NO_DLOPEN */ + +static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename) +{ + ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, cmd->pool, APLOGNO(01577) + "WARNING: LoadFile not supported on this platform"); + return NULL; +} + +static const char *load_module(cmd_parms *cmd, void *dummy, + const char *modname, const char *filename) +{ + ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, cmd->pool, APLOGNO(01578) + "WARNING: LoadModule not supported on this platform"); + return NULL; +} + +#endif /* NO_DLOPEN */ + +static void register_hooks(apr_pool_t *p) +{ +#ifndef NO_DLOPEN + APR_REGISTER_OPTIONAL_FN(ap_find_loaded_module_symbol); + ap_hook_test_config(dump_loaded_modules, NULL, NULL, APR_HOOK_MIDDLE); +#endif +} + +static const command_rec so_cmds[] = { + AP_INIT_TAKE2("LoadModule", load_module, NULL, RSRC_CONF | EXEC_ON_READ, + "a module name and the name of a shared object file to load it from"), + AP_INIT_ITERATE("LoadFile", load_file, NULL, RSRC_CONF | EXEC_ON_READ, + "shared object file or library to load into the server at runtime"), + { NULL } +}; + +AP_DECLARE_MODULE(so) = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + so_sconf_create, /* server config */ + NULL, /* merge server config */ + so_cmds, /* command apr_table_t */ + register_hooks /* register hooks */ +}; diff --git a/modules/core/mod_so.h b/modules/core/mod_so.h new file mode 100644 index 0000000..2b26999 --- /dev/null +++ b/modules/core/mod_so.h @@ -0,0 +1,38 @@ +/* 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. + */ + +/** + * @file mod_so.h + * @brief Shared Object Loader Extension Module for Apache + * + * @defgroup MOD_SO mod_so + * @ingroup APACHE_MODS + * @{ + */ + +#ifndef MOD_SO_H +#define MOD_SO_H 1 + +#include "apr_optional.h" +#include "httpd.h" + +/* optional function declaration */ +APR_DECLARE_OPTIONAL_FN(module *, ap_find_loaded_module_symbol, + (server_rec *s, const char *modname)); + +#endif /* MOD_SO_H */ +/** @} */ + diff --git a/modules/core/mod_watchdog.c b/modules/core/mod_watchdog.c new file mode 100644 index 0000000..99ec7cf --- /dev/null +++ b/modules/core/mod_watchdog.c @@ -0,0 +1,718 @@ +/* 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. + */ + +/* Watchdog module. + */ + +#include "apr.h" +#include "mod_watchdog.h" +#include "ap_provider.h" +#include "ap_mpm.h" +#include "http_core.h" +#include "util_mutex.h" + +#include "apr_atomic.h" + +#define AP_WATCHDOG_PGROUP "watchdog" +#define AP_WATCHDOG_PVERSION "parent" +#define AP_WATCHDOG_CVERSION "child" + +typedef struct watchdog_list_t watchdog_list_t; + +struct watchdog_list_t +{ + struct watchdog_list_t *next; + ap_watchdog_t *wd; + apr_status_t status; + apr_interval_time_t interval; + apr_interval_time_t step; + const void *data; + ap_watchdog_callback_fn_t *callback_fn; +}; + +struct ap_watchdog_t +{ + apr_uint32_t thread_started; /* set to 1 once thread running */ + apr_proc_mutex_t *mutex; + const char *name; + watchdog_list_t *callbacks; + int is_running; + int singleton; + int active; + apr_interval_time_t step; + apr_thread_t *thread; + apr_pool_t *pool; +}; + +typedef struct wd_server_conf_t wd_server_conf_t; +struct wd_server_conf_t +{ + int child_workers; + int parent_workers; + apr_pool_t *pool; + server_rec *s; +}; + +static wd_server_conf_t *wd_server_conf = NULL; +static apr_interval_time_t wd_interval = AP_WD_TM_INTERVAL; +static int mpm_is_forked = AP_MPMQ_NOT_SUPPORTED; +static const char *wd_proc_mutex_type = "watchdog-callback"; + +static apr_status_t wd_worker_cleanup(void *data) +{ + apr_status_t rv; + ap_watchdog_t *w = (ap_watchdog_t *)data; + + /* Do nothing if the thread wasn't started. */ + if (apr_atomic_read32(&w->thread_started) != 1) + return APR_SUCCESS; + + if (w->is_running) { + watchdog_list_t *wl = w->callbacks; + while (wl) { + if (wl->status == APR_SUCCESS) { + /* Execute watchdog callback with STOPPING state */ + (*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING, + (void *)wl->data, w->pool); + wl->status = APR_EOF; + } + wl = wl->next; + } + } + w->is_running = 0; + apr_thread_join(&rv, w->thread); + return rv; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* Main watchdog worker thread. */ +/* For singleton workers child thread that first obtains the process */ +/* mutex is running. Threads in other child's are locked on mutex. */ +/* */ +/*--------------------------------------------------------------------------*/ +static void* APR_THREAD_FUNC wd_worker(apr_thread_t *thread, void *data) +{ + ap_watchdog_t *w = (ap_watchdog_t *)data; + apr_status_t rv; + int locked = 0; + int probed = 0; + int inited = 0; + int mpmq_s = 0; + apr_pool_t *temp_pool = NULL; + + w->pool = apr_thread_pool_get(thread); + w->is_running = 1; + + apr_atomic_set32(&w->thread_started, 1); /* thread started */ + + if (w->mutex) { + while (w->is_running) { + if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) { + w->is_running = 0; + break; + } + if (mpmq_s == AP_MPMQ_STOPPING) { + w->is_running = 0; + break; + } + rv = apr_proc_mutex_trylock(w->mutex); + if (rv == APR_SUCCESS) { + if (probed) { + /* Sleep after we were locked + * up to 1 second. Httpd can be + * in the middle of shutdown, and + * our child didn't yet received + * the shutdown signal. + */ + probed = 10; + while (w->is_running && probed > 0) { + apr_sleep(AP_WD_TM_INTERVAL); + probed--; + if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) { + w->is_running = 0; + break; + } + if (mpmq_s == AP_MPMQ_STOPPING) { + w->is_running = 0; + break; + } + } + } + locked = 1; + break; + } + probed = 1; + apr_sleep(AP_WD_TM_SLICE); + } + } + + apr_pool_create(&temp_pool, w->pool); + apr_pool_tag(temp_pool, "wd_running"); + + if (w->is_running) { + watchdog_list_t *wl = w->callbacks; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s, + APLOGNO(02972) "%sWatchdog (%s) running", + w->singleton ? "Singleton " : "", w->name); + apr_time_clock_hires(w->pool); + if (wl) { + while (wl && w->is_running) { + /* Execute watchdog callback */ + wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_STARTING, + (void *)wl->data, temp_pool); + wl = wl->next; + } + apr_pool_clear(temp_pool); + } + else { + ap_run_watchdog_init(wd_server_conf->s, w->name, w->pool); + inited = 1; + } + } + + /* Main execution loop */ + while (w->is_running) { + apr_time_t curr; + watchdog_list_t *wl = w->callbacks; + + apr_sleep(AP_WD_TM_SLICE); + if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) { + w->is_running = 0; + } + if (mpmq_s == AP_MPMQ_STOPPING) { + w->is_running = 0; + } + if (!w->is_running) { + break; + } + curr = apr_time_now() - AP_WD_TM_SLICE; + while (wl && w->is_running) { + if (wl->status == APR_SUCCESS) { + wl->step += (apr_time_now() - curr); + if (wl->step >= wl->interval) { + wl->step = 0; + /* Execute watchdog callback */ + wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_RUNNING, + (void *)wl->data, temp_pool); + if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) { + w->is_running = 0; + } + if (mpmq_s == AP_MPMQ_STOPPING) { + w->is_running = 0; + } + } + } + wl = wl->next; + } + if (w->is_running && w->callbacks == NULL) { + /* This is hook mode watchdog + * running on WatchogInterval + */ + w->step += (apr_time_now() - curr); + if (w->step >= wd_interval) { + w->step = 0; + /* Run watchdog step hook */ + ap_run_watchdog_step(wd_server_conf->s, w->name, temp_pool); + } + } + + apr_pool_clear(temp_pool); + } + + apr_pool_destroy(temp_pool); + + if (inited) { + /* Run the watchdog exit hooks. + * If this was singleton watchdog the init hook + * might never been called, so skip the exit hook + * in that case as well. + */ + ap_run_watchdog_exit(wd_server_conf->s, w->name, w->pool); + } + else { + watchdog_list_t *wl = w->callbacks; + while (wl) { + if (wl->status == APR_SUCCESS) { + /* Execute watchdog callback with STOPPING state */ + (*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING, + (void *)wl->data, w->pool); + } + wl = wl->next; + } + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s, + APLOGNO(02973) "%sWatchdog (%s) stopping", + w->singleton ? "Singleton " : "", w->name); + + if (locked) + apr_proc_mutex_unlock(w->mutex); + apr_thread_exit(w->thread, APR_SUCCESS); + + return NULL; +} + +static apr_status_t wd_startup(ap_watchdog_t *w, apr_pool_t *p) +{ + apr_status_t rc; + + apr_atomic_set32(&w->thread_started, 0); + + if (w->singleton) { + /* Initialize singleton mutex in child */ + rc = apr_proc_mutex_child_init(&w->mutex, + apr_proc_mutex_lockfile(w->mutex), p); + if (rc != APR_SUCCESS) + return rc; + } + + /* Start the newly created watchdog */ + rc = ap_thread_create(&w->thread, NULL, wd_worker, w, p); + if (rc == APR_SUCCESS) { + apr_pool_pre_cleanup_register(p, w, wd_worker_cleanup); + } + + return rc; +} + +static apr_status_t ap_watchdog_get_instance(ap_watchdog_t **watchdog, + const char *name, + int parent, + int singleton, + apr_pool_t *p) +{ + ap_watchdog_t *w; + const char *pver = parent ? AP_WATCHDOG_PVERSION : AP_WATCHDOG_CVERSION; + + if (parent && mpm_is_forked != AP_MPMQ_NOT_SUPPORTED) { + /* Parent threads are not supported for + * forked mpm's + */ + *watchdog = NULL; + return APR_ENOTIMPL; + } + w = ap_lookup_provider(AP_WATCHDOG_PGROUP, name, pver); + if (w) { + *watchdog = w; + return APR_SUCCESS; + } + w = apr_pcalloc(p, sizeof(ap_watchdog_t)); + w->name = name; + w->pool = p; + w->singleton = parent ? 0 : singleton; + *watchdog = w; + return ap_register_provider(p, AP_WATCHDOG_PGROUP, name, + pver, *watchdog); +} + +static apr_status_t ap_watchdog_set_callback_interval(ap_watchdog_t *w, + apr_interval_time_t interval, + const void *data, + ap_watchdog_callback_fn_t *callback) +{ + watchdog_list_t *c = w->callbacks; + apr_status_t rv = APR_EOF; + + while (c) { + if (c->data == data && c->callback_fn == callback) { + /* We have existing callback. + * Update the interval and reset status, so the + * callback and continue execution if stopped earlier. + */ + c->interval = interval; + c->step = 0; + c->status = APR_SUCCESS; + rv = APR_SUCCESS; + break; + } + c = c->next; + } + return rv; +} + +static apr_status_t ap_watchdog_register_callback(ap_watchdog_t *w, + apr_interval_time_t interval, + const void *data, + ap_watchdog_callback_fn_t *callback) +{ + watchdog_list_t *c = w->callbacks; + + while (c) { + if (c->data == data && c->callback_fn == callback) { + /* We have already registered callback. + * Do not allow callbacks that have the same + * function and data pointers. + */ + return APR_EEXIST; + } + c = c->next; + } + c = apr_palloc(w->pool, sizeof(watchdog_list_t)); + c->data = data; + c->callback_fn = callback; + c->interval = interval; + c->step = 0; + c->status = APR_EINIT; + + c->wd = w; + c->next = w->callbacks; + w->callbacks = c; + w->active++; + + return APR_SUCCESS; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* Pre config hook. */ +/* Create default watchdogs for parent and child */ +/* Parent watchdog executes inside parent process so it doesn't need the */ +/* singleton mutex */ +/* */ +/*--------------------------------------------------------------------------*/ +static int wd_pre_config_hook(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptemp) +{ + apr_status_t rv; + ap_watchdog_t *w; + + ap_mpm_query(AP_MPMQ_IS_FORKED, &mpm_is_forked); + if ((rv = ap_watchdog_get_instance(&w, + AP_WATCHDOG_SINGLETON, 0, 1, pconf)) != APR_SUCCESS) { + return rv; + } + if ((rv = ap_watchdog_get_instance(&w, + AP_WATCHDOG_DEFAULT, 0, 0, pconf)) != APR_SUCCESS) { + return rv; + } + if (mpm_is_forked == AP_MPMQ_NOT_SUPPORTED) { + /* Create parent process watchdog for + * non forked mpm's only. + */ + if ((rv = ap_watchdog_get_instance(&w, + AP_WATCHDOG_DEFAULT, 1, 0, pconf)) != APR_SUCCESS) { + return rv; + } + } + + if ((rv = ap_mutex_register(pconf, wd_proc_mutex_type, NULL, + APR_LOCK_DEFAULT, 0)) != APR_SUCCESS) { + return rv; + } + + return OK; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* Post config hook. */ +/* Create watchdog thread in parent and initializes Watchdog module */ +/* */ +/*--------------------------------------------------------------------------*/ +static int wd_post_config_hook(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s) +{ + apr_status_t rv; + const char *pk = "watchdog_init_module_tag"; + apr_pool_t *ppconf = pconf; + const apr_array_header_t *wl; + + if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) + /* First time config phase -- skip. */ + return OK; + + apr_pool_userdata_get((void *)&wd_server_conf, pk, ppconf); + if (!wd_server_conf) { + if (!(wd_server_conf = apr_pcalloc(ppconf, sizeof(wd_server_conf_t)))) + return APR_ENOMEM; + apr_pool_create(&wd_server_conf->pool, ppconf); + apr_pool_tag(wd_server_conf->pool, "wd_server_conf"); + apr_pool_userdata_set(wd_server_conf, pk, apr_pool_cleanup_null, ppconf); + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(010033) + "Watchdog: Running with WatchdogInterval %" + APR_TIME_T_FMT "ms", apr_time_as_msec(wd_interval)); + wd_server_conf->s = s; + if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP, + AP_WATCHDOG_PVERSION))) { + const ap_list_provider_names_t *wn; + int i; + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02974) + "Watchdog: found parent providers."); + + wn = (ap_list_provider_names_t *)wl->elts; + for (i = 0; i < wl->nelts; i++) { + ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP, + wn[i].provider_name, + AP_WATCHDOG_PVERSION); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02975) + "Watchdog: Looking for parent (%s).", wn[i].provider_name); + if (w) { + if (!w->active) { + int status = ap_run_watchdog_need(s, w->name, 1, + w->singleton); + if (status == OK) { + /* One of the modules returned OK to this watchdog. + * Mark it as active + */ + w->active = 1; + } + } + if (w->active) { + /* We have active watchdog. + * Create the watchdog thread + */ + if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01571) + "Watchdog: Failed to create parent worker thread."); + return rv; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02976) + "Watchdog: Created parent worker thread (%s).", w->name); + wd_server_conf->parent_workers++; + } + } + } + } + if (wd_server_conf->parent_workers) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01572) + "Spawned %d parent worker threads.", + wd_server_conf->parent_workers); + } + if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP, + AP_WATCHDOG_CVERSION))) { + const ap_list_provider_names_t *wn; + int i; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02977) + "Watchdog: found child providers."); + + wn = (ap_list_provider_names_t *)wl->elts; + for (i = 0; i < wl->nelts; i++) { + ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP, + wn[i].provider_name, + AP_WATCHDOG_CVERSION); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02978) + "Watchdog: Looking for child (%s).", wn[i].provider_name); + if (w) { + if (!w->active) { + int status = ap_run_watchdog_need(s, w->name, 0, + w->singleton); + if (status == OK) { + /* One of the modules returned OK to this watchdog. + * Mark it as active + */ + w->active = 1; + } + } + if (w->active) { + /* We have some callbacks registered. + * Create mutexes for singleton watchdogs + */ + if (w->singleton) { + rv = ap_proc_mutex_create(&w->mutex, NULL, wd_proc_mutex_type, + w->name, s, + wd_server_conf->pool, 0); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(10095) + "Watchdog: Failed to create singleton mutex."); + return rv; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02979) + "Watchdog: Created singleton mutex (%s).", w->name); + } + wd_server_conf->child_workers++; + } + } + } + } + return OK; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* Child init hook. */ +/* Create watchdog threads and initializes Mutexes in child */ +/* */ +/*--------------------------------------------------------------------------*/ +static void wd_child_init_hook(apr_pool_t *p, server_rec *s) +{ + apr_status_t rv = OK; + const apr_array_header_t *wl; + + if (!wd_server_conf->child_workers) { + /* We don't have anything configured, bail out. + */ + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02980) + "Watchdog: nothing configured?"); + return; + } + if ((wl = ap_list_provider_names(p, AP_WATCHDOG_PGROUP, + AP_WATCHDOG_CVERSION))) { + const ap_list_provider_names_t *wn; + int i; + wn = (ap_list_provider_names_t *)wl->elts; + for (i = 0; i < wl->nelts; i++) { + ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP, + wn[i].provider_name, + AP_WATCHDOG_CVERSION); + if (w && w->active) { + /* We have some callbacks registered. + * Kick of the watchdog + */ + if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01573) + "Watchdog: Failed to create child worker thread."); + /* No point to continue */ + return; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02981) + "Watchdog: Created child worker thread (%s).", wn[i].provider_name); + } + } + } +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* WatchdogInterval directive */ +/* */ +/*--------------------------------------------------------------------------*/ +static const char *wd_cmd_watchdog_int(cmd_parms *cmd, void *dummy, + const char *arg) +{ + apr_status_t rv; + const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY); + + if (errs != NULL) + return errs; + rv = ap_timeout_parameter_parse(arg, &wd_interval, "s"); + + if (rv != APR_SUCCESS) + return "Unparse-able WatchdogInterval setting"; + if (wd_interval < AP_WD_TM_SLICE) { + return apr_psprintf(cmd->pool, "Invalid WatchdogInterval: minimal value %" + APR_TIME_T_FMT "ms", apr_time_as_msec(AP_WD_TM_SLICE)); + } + + return NULL; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* List of directives specific to our module. */ +/* */ +/*--------------------------------------------------------------------------*/ +static const command_rec wd_directives[] = +{ + AP_INIT_TAKE1( + "WatchdogInterval", /* directive name */ + wd_cmd_watchdog_int, /* config action routine */ + NULL, /* argument to include in call */ + RSRC_CONF, /* where available */ + "Watchdog interval in seconds" + ), + {NULL} +}; + +/*--------------------------------------------------------------------------*/ +/* */ +/* Which functions are responsible for which hooks in the server. */ +/* */ +/*--------------------------------------------------------------------------*/ +static void wd_register_hooks(apr_pool_t *p) +{ + + /* Only the mpm_winnt has child init hook handler. + * Make sure that we are called after the mpm child init handler + * initializes. + */ + static const char *const after_mpm[] = { "mpm_winnt.c", NULL}; + + /* Pre config handling + */ + ap_hook_pre_config(wd_pre_config_hook, + NULL, + NULL, + APR_HOOK_FIRST); + + /* Post config handling + */ + ap_hook_post_config(wd_post_config_hook, + NULL, + NULL, + APR_HOOK_LAST); + + /* Child init hook + */ + ap_hook_child_init(wd_child_init_hook, + after_mpm, + NULL, + APR_HOOK_MIDDLE); + + APR_REGISTER_OPTIONAL_FN(ap_watchdog_get_instance); + APR_REGISTER_OPTIONAL_FN(ap_watchdog_register_callback); + APR_REGISTER_OPTIONAL_FN(ap_watchdog_set_callback_interval); +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* The list of callback routines and data structures that provide */ +/* the static hooks into our module from the other parts of the server. */ +/* */ +/*--------------------------------------------------------------------------*/ +AP_DECLARE_MODULE(watchdog) = { + 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 */ + wd_directives, /* command apr_table_t */ + wd_register_hooks /* register hooks */ +}; + +/*--------------------------------------------------------------------------*/ +/* */ +/* The list of optional hooks that we provide */ +/* */ +/*--------------------------------------------------------------------------*/ +APR_HOOK_STRUCT( + APR_HOOK_LINK(watchdog_need) + APR_HOOK_LINK(watchdog_init) + APR_HOOK_LINK(watchdog_exit) + APR_HOOK_LINK(watchdog_step) +) + +APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ap, AP_WD, int, watchdog_need, + (server_rec *s, const char *name, + int parent, int singleton), + (s, name, parent, singleton), + DECLINED) +APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_init, + (server_rec *s, const char *name, + apr_pool_t *pool), + (s, name, pool), + OK, DECLINED) +APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_exit, + (server_rec *s, const char *name, + apr_pool_t *pool), + (s, name, pool), + OK, DECLINED) +APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_step, + (server_rec *s, const char *name, + apr_pool_t *pool), + (s, name, pool), + OK, DECLINED) diff --git a/modules/core/mod_watchdog.dep b/modules/core/mod_watchdog.dep new file mode 100644 index 0000000..147475b --- /dev/null +++ b/modules/core/mod_watchdog.dep @@ -0,0 +1,59 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_watchdog.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + + +.\mod_watchdog.c : \ + "..\..\include\ap_config.h"\ + "..\..\include\ap_config_layout.h"\ + "..\..\include\ap_expr.h"\ + "..\..\include\ap_hooks.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_mpm.h"\ + "..\..\include\ap_provider.h"\ + "..\..\include\ap_regex.h"\ + "..\..\include\ap_release.h"\ + "..\..\include\apache_noprobes.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\os.h"\ + "..\..\include\scoreboard.h"\ + "..\..\include\util_cfgtree.h"\ + "..\..\include\util_filter.h"\ + "..\..\include\util_mutex.h"\ + "..\..\srclib\apr-util\include\apr_buckets.h"\ + "..\..\srclib\apr-util\include\apr_hooks.h"\ + "..\..\srclib\apr-util\include\apr_optional.h"\ + "..\..\srclib\apr-util\include\apr_optional_hooks.h"\ + "..\..\srclib\apr-util\include\apr_uri.h"\ + "..\..\srclib\apr-util\include\apu.h"\ + "..\..\srclib\apr\include\apr.h"\ + "..\..\srclib\apr\include\apr_allocator.h"\ + "..\..\srclib\apr\include\apr_dso.h"\ + "..\..\srclib\apr\include\apr_errno.h"\ + "..\..\srclib\apr\include\apr_file_info.h"\ + "..\..\srclib\apr\include\apr_file_io.h"\ + "..\..\srclib\apr\include\apr_general.h"\ + "..\..\srclib\apr\include\apr_global_mutex.h"\ + "..\..\srclib\apr\include\apr_hash.h"\ + "..\..\srclib\apr\include\apr_inherit.h"\ + "..\..\srclib\apr\include\apr_mmap.h"\ + "..\..\srclib\apr\include\apr_network_io.h"\ + "..\..\srclib\apr\include\apr_poll.h"\ + "..\..\srclib\apr\include\apr_pools.h"\ + "..\..\srclib\apr\include\apr_portable.h"\ + "..\..\srclib\apr\include\apr_proc_mutex.h"\ + "..\..\srclib\apr\include\apr_ring.h"\ + "..\..\srclib\apr\include\apr_shm.h"\ + "..\..\srclib\apr\include\apr_strings.h"\ + "..\..\srclib\apr\include\apr_tables.h"\ + "..\..\srclib\apr\include\apr_thread_mutex.h"\ + "..\..\srclib\apr\include\apr_thread_proc.h"\ + "..\..\srclib\apr\include\apr_time.h"\ + "..\..\srclib\apr\include\apr_user.h"\ + "..\..\srclib\apr\include\apr_want.h"\ + ".\mod_watchdog.h"\ + diff --git a/modules/core/mod_watchdog.dsp b/modules/core/mod_watchdog.dsp new file mode 100644 index 0000000..fcb1f28 --- /dev/null +++ b/modules/core/mod_watchdog.dsp @@ -0,0 +1,115 @@ +# Microsoft Developer Studio Project File - Name="mod_watchdog" - 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_watchdog - 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_watchdog.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_watchdog.mak" CFG="mod_watchdog - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_watchdog - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_watchdog - 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_watchdog - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "AP_WD_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_watchdog_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 /fo"Release/mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" +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_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_watchdog.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_watchdog - 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 "AP_WD_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_watchdog_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 /fo"Debug/mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" +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_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_watchdog.so" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_watchdog.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_watchdog - Win32 Release" +# Name "mod_watchdog - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_watchdog.c +# End Source File +# Begin Source File + +SOURCE=.\mod_watchdog.h +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/modules/core/mod_watchdog.h b/modules/core/mod_watchdog.h new file mode 100644 index 0000000..8e7112c --- /dev/null +++ b/modules/core/mod_watchdog.h @@ -0,0 +1,213 @@ +/* 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_WATCHDOG_H +#define MOD_WATCHDOG_H + +/** + * @file mod_watchdog.h + * @brief Watchdog module for Apache + * + * @defgroup MOD_WATCHDOG mod_watchdog + * @ingroup APACHE_MODS + * @{ + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "ap_provider.h" + +#include "apr.h" +#include "apr_strings.h" +#include "apr_pools.h" +#include "apr_shm.h" +#include "apr_hash.h" +#include "apr_hooks.h" +#include "apr_optional.h" +#include "apr_file_io.h" +#include "apr_time.h" +#include "apr_thread_proc.h" +#include "apr_global_mutex.h" +#include "apr_thread_mutex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Default singleton watchdog instance name. + * Singleton watchdog is protected by mutex and + * guaranteed to be run inside a single child process + * at any time. + */ +#define AP_WATCHDOG_SINGLETON "_singleton_" + +/** + * Default watchdog instance name + */ +#define AP_WATCHDOG_DEFAULT "_default_" + +/** + * Default Watchdog interval + */ +#define AP_WD_TM_INTERVAL APR_TIME_C(1000000) /* 1 second */ + +/** + * Watchdog thread timer resolution + */ +#define AP_WD_TM_SLICE APR_TIME_C(100000) /* 100 ms */ + +/* State values for callback */ +#define AP_WATCHDOG_STATE_STARTING 1 +#define AP_WATCHDOG_STATE_RUNNING 2 +#define AP_WATCHDOG_STATE_STOPPING 3 + +typedef struct ap_watchdog_t ap_watchdog_t; + +/* Create a set of AP_WD_DECLARE(type), AP_WD_DECLARE_NONSTD(type) and + * AP_WD_DECLARE_DATA with appropriate export and import tags for the platform + */ +#if !defined(AP_WD_DECLARE) +#if !defined(WIN32) +#define AP_WD_DECLARE(type) type +#define AP_WD_DECLARE_NONSTD(type) type +#define AP_WD_DECLARE_DATA +#elif defined(AP_WD_DECLARE_STATIC) +#define AP_WD_DECLARE(type) type __stdcall +#define AP_WD_DECLARE_NONSTD(type) type +#define AP_WD_DECLARE_DATA +#elif defined(AP_WD_DECLARE_EXPORT) +#define AP_WD_DECLARE(type) __declspec(dllexport) type __stdcall +#define AP_WD_DECLARE_NONSTD(type) __declspec(dllexport) type +#define AP_WD_DECLARE_DATA __declspec(dllexport) +#else +#define AP_WD_DECLARE(type) __declspec(dllimport) type __stdcall +#define AP_WD_DECLARE_NONSTD(type) __declspec(dllimport) type +#define AP_WD_DECLARE_DATA __declspec(dllimport) +#endif +#endif + +/** + * Callback function used for watchdog. + * @param state Watchdog state function. See @p AP_WATCHDOG_STATE_ . + * @param data is what was passed to @p ap_watchdog_register_callback function. + * @param pool Temporary callback pool destroyed after the call. + * @return APR_SUCCESS to continue calling this callback. + */ +typedef apr_status_t ap_watchdog_callback_fn_t(int state, void *data, + apr_pool_t *pool); + +/** + * Get watchdog instance. + * @param watchdog Storage for watchdog instance. + * @param name Watchdog name. + * @param parent Non-zero to get the parent process watchdog instance. + * @param singleton Non-zero to get the singleton watchdog instance. + * @param p The pool to use. + * @return APR_SUCCESS if all went well + * @remark Use @p AP_WATCHDOG_DEFAULT to get default watchdog instance. + * If separate watchdog thread is needed provide unique name + * and function will create a new watchdog instance. + * Note that default client process watchdog works in singleton mode. + */ +APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_watchdog_get_instance, + (ap_watchdog_t **watchdog, const char *name, int parent, + int singleton, apr_pool_t *p)); + +/** + * Register watchdog callback. + * @param watchdog Watchdog to use + * @param interval Interval on which the callback function will execute. + * @param callback The function to call on watchdog event. + * @param data The data to pass to the callback function. + * @return APR_SUCCESS if all went well. APR_EEXIST if already registered. + */ +APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_watchdog_register_callback, + (ap_watchdog_t *watchdog, apr_interval_time_t interval, + const void *data, ap_watchdog_callback_fn_t *callback)); + +/** + * Update registered watchdog callback interval. + * @param w Watchdog to use + * @param interval New interval on which the callback function will execute. + * @param callback The function to call on watchdog event. + * @param data The data to pass to the callback function. + * @return APR_SUCCESS if all went well. APR_EOF if callback was not found. + */ +APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_watchdog_set_callback_interval, + (ap_watchdog_t *w, apr_interval_time_t interval, + const void *data, ap_watchdog_callback_fn_t *callback)); + +/** + * Watchdog require hook. + * @param s The server record + * @param name Watchdog name. + * @param parent Non-zero to indicate the parent process watchdog mode. + * @param singleton Non-zero to indicate the singleton watchdog mode. + * @return OK to enable notifications from this watchdog, DECLINED otherwise. + * @remark This is called in post config phase for all watchdog instances + * that have no callbacks registered. Modules using this hook + * should ensure that their post_config hook is called after watchdog + * post_config. + */ +APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_need, (server_rec *s, + const char *name, + int parent, int singleton)) + + +/** + * Watchdog initialize hook. + * It is called after the watchdog thread is initialized. + * @param s The server record + * @param name Watchdog name. + * @param pool The pool used to create the watchdog. + */ +APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_init, ( + server_rec *s, + const char *name, + apr_pool_t *pool)) + +/** + * Watchdog terminate hook. + * It is called when the watchdog thread is terminated. + * @param s The server record + * @param name Watchdog name. + * @param pool The pool used to create the watchdog. + */ +APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_exit, ( + server_rec *s, + const char *name, + apr_pool_t *pool)) + +/** + * Fixed interval watchdog hook. + * It is called regularly on @p AP_WD_TM_INTERVAL interval. + * @param s The server record + * @param name Watchdog name. + * @param pool Temporary pool destroyed after the call. + */ +APR_DECLARE_EXTERNAL_HOOK(ap, AP_WD, int, watchdog_step, ( + server_rec *s, + const char *name, + apr_pool_t *pool)) + +#ifdef __cplusplus +} +#endif + +#endif /* MOD_WATCHDOG_H */ +/** @} */ diff --git a/modules/core/mod_watchdog.mak b/modules/core/mod_watchdog.mak new file mode 100644 index 0000000..6b58c6d --- /dev/null +++ b/modules/core/mod_watchdog.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_watchdog.dsp +!IF "$(CFG)" == "" +CFG=mod_watchdog - Win32 Release +!MESSAGE No configuration specified. Defaulting to mod_watchdog - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "mod_watchdog - Win32 Release" && "$(CFG)" != "mod_watchdog - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_watchdog.mak" CFG="mod_watchdog - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_watchdog - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_watchdog - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_watchdog - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_watchdog.obj" + -@erase "$(INTDIR)\mod_watchdog.res" + -@erase "$(INTDIR)\mod_watchdog_src.idb" + -@erase "$(INTDIR)\mod_watchdog_src.pdb" + -@erase "$(OUTDIR)\mod_watchdog.exp" + -@erase "$(OUTDIR)\mod_watchdog.lib" + -@erase "$(OUTDIR)\mod_watchdog.pdb" + -@erase "$(OUTDIR)\mod_watchdog.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "AP_WD_DECLARE_EXPORT" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_watchdog_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_watchdog.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_watchdog.pdb" /debug /out:"$(OUTDIR)\mod_watchdog.so" /implib:"$(OUTDIR)\mod_watchdog.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_watchdog.obj" \ + "$(INTDIR)\mod_watchdog.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_watchdog.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_watchdog.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_watchdog.so" + if exist .\Release\mod_watchdog.so.manifest mt.exe -manifest .\Release\mod_watchdog.so.manifest -outputresource:.\Release\mod_watchdog.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_watchdog.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_watchdog.obj" + -@erase "$(INTDIR)\mod_watchdog.res" + -@erase "$(INTDIR)\mod_watchdog_src.idb" + -@erase "$(INTDIR)\mod_watchdog_src.pdb" + -@erase "$(OUTDIR)\mod_watchdog.exp" + -@erase "$(OUTDIR)\mod_watchdog.lib" + -@erase "$(OUTDIR)\mod_watchdog.pdb" + -@erase "$(OUTDIR)\mod_watchdog.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "AP_WD_DECLARE_EXPORT" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_watchdog_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_watchdog.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_watchdog.pdb" /debug /out:"$(OUTDIR)\mod_watchdog.so" /implib:"$(OUTDIR)\mod_watchdog.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_watchdog.so +LINK32_OBJS= \ + "$(INTDIR)\mod_watchdog.obj" \ + "$(INTDIR)\mod_watchdog.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_watchdog.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_watchdog.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_watchdog.so" + if exist .\Debug\mod_watchdog.so.manifest mt.exe -manifest .\Debug\mod_watchdog.so.manifest -outputresource:.\Debug\mod_watchdog.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_watchdog.dep") +!INCLUDE "mod_watchdog.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_watchdog.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_watchdog - Win32 Release" || "$(CFG)" == "mod_watchdog - Win32 Debug" + +!IF "$(CFG)" == "mod_watchdog - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\core" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\core" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ENDIF + +!IF "$(CFG)" == "mod_watchdog - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\core" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\core" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\core" + +!ENDIF + +!IF "$(CFG)" == "mod_watchdog - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\core" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\core" + +!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\core" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\core" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_watchdog - Win32 Release" + + +"$(INTDIR)\mod_watchdog.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_watchdog - Win32 Debug" + + +"$(INTDIR)\mod_watchdog.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_watchdog.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_watchdog.so" /d LONG_NAME="watchdog_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_watchdog.c + +"$(INTDIR)\mod_watchdog.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/core/test/Makefile b/modules/core/test/Makefile new file mode 100644 index 0000000..bd2a6cb --- /dev/null +++ b/modules/core/test/Makefile @@ -0,0 +1,67 @@ +# +# mod_macro non regression tests + +# where is apache +APA.dir = /tmp/apache + +# apache executable with mod macro loaded +HTTPD = \ + $(APA.dir)/bin/httpd \ + -C 'LoadModule macro_module modules/mod_macro.so' \ + -C "Define PWD $$PWD/conf" + +# default target +.PHONY: default +default: clean + +# run all non regression tests +.PHONY: check +check: check-out + +# result directory +OUT = out +out: + mkdir $@ + +# test cases & results +F.conf = $(wildcard conf/test*.conf) +F.out = $(F.conf:conf/%.conf=$(OUT)/%.out) + +# run all tests +.PHONY: run-test +run-test: $(F.out) + +# generate & compare in a separate directory +.PHONY: check-out +check-out: out + $(RM) out/*.out + $(MAKE) OUT=out run-test + diff -r out/ ref/ + +# generate & compare in the same directory +.PHONY: check-ref +check-ref: + $(RM) ref/*.out + $(MAKE) OUT=ref run-test + svn diff ref/ + +# run one test case +# filter output so that it is portable +# use '|' sed separator because $PWD will contain plenty '/' +$(OUT)/%.out: conf/%.conf + { \ + echo "# testing with $<" ; \ + $(HTTPD) -f $$PWD/$< 2>&1 ; \ + echo "# exit: $$?" ; \ + } > $@.tmp ; \ + sed -e "s|$$PWD|.|g" \ + -e "s|^\[[\.a-zA-Z0-9 :]*\] ||" \ + -e "s|\[pid [0-9]*:tid [0-9]*] ||" \ + $@.tmp > $@ ; \ + $(RM) $@.tmp + +# cleanup +.PHONY: clean +clean: + $(RM) *~ + $(RM) -r out diff --git a/modules/core/test/conf/inc63_1.conf b/modules/core/test/conf/inc63_1.conf new file mode 100644 index 0000000..6a436f9 --- /dev/null +++ b/modules/core/test/conf/inc63_1.conf @@ -0,0 +1,5 @@ +# macro for include + + Warning "Foo macro at $where" + +Use Foo "inc63_.conf:5" diff --git a/modules/core/test/conf/inc63_2.conf b/modules/core/test/conf/inc63_2.conf new file mode 100644 index 0000000..3a0da9e --- /dev/null +++ b/modules/core/test/conf/inc63_2.conf @@ -0,0 +1,3 @@ +# use macro defined elsewhere +Use Foo "inc63_2.conf:2" +Use Bla "inc63_2.conf:3" diff --git a/modules/core/test/conf/test01.conf b/modules/core/test/conf/test01.conf new file mode 100644 index 0000000..9a3d9ab --- /dev/null +++ b/modules/core/test/conf/test01.conf @@ -0,0 +1,3 @@ +# no macro name + + diff --git a/modules/core/test/conf/test02.conf b/modules/core/test/conf/test02.conf new file mode 100644 index 0000000..1fe4b41 --- /dev/null +++ b/modules/core/test/conf/test02.conf @@ -0,0 +1,3 @@ +# no macro name and spaces + + diff --git a/modules/core/test/conf/test03.conf b/modules/core/test/conf/test03.conf new file mode 100644 index 0000000..fdcf4c8 --- /dev/null +++ b/modules/core/test/conf/test03.conf @@ -0,0 +1,5 @@ +# use undefined macro + + Warning "macro foo" + +Use bla diff --git a/modules/core/test/conf/test04.conf b/modules/core/test/conf/test04.conf new file mode 100644 index 0000000..8228775 --- /dev/null +++ b/modules/core/test/conf/test04.conf @@ -0,0 +1,5 @@ +# wrong args + + Warning "macro foo" + +Use foo hello diff --git a/modules/core/test/conf/test05.conf b/modules/core/test/conf/test05.conf new file mode 100644 index 0000000..2166aca --- /dev/null +++ b/modules/core/test/conf/test05.conf @@ -0,0 +1,5 @@ +# wrong args + + Warning "macro foo $premier" + +Use foo diff --git a/modules/core/test/conf/test06.conf b/modules/core/test/conf/test06.conf new file mode 100644 index 0000000..35e6b68 --- /dev/null +++ b/modules/core/test/conf/test06.conf @@ -0,0 +1,6 @@ +# wrong args + + Warning "macro foo $premier" + +Use foo one two + diff --git a/modules/core/test/conf/test07.conf b/modules/core/test/conf/test07.conf new file mode 100644 index 0000000..06f050e --- /dev/null +++ b/modules/core/test/conf/test07.conf @@ -0,0 +1,3 @@ +# missing end macro + +hello diff --git a/modules/core/test/conf/test08.conf b/modules/core/test/conf/test08.conf new file mode 100644 index 0000000..333dbd9 --- /dev/null +++ b/modules/core/test/conf/test08.conf @@ -0,0 +1,3 @@ +# missing begin macro +ServerName hello + diff --git a/modules/core/test/conf/test09.conf b/modules/core/test/conf/test09.conf new file mode 100644 index 0000000..2513b6e --- /dev/null +++ b/modules/core/test/conf/test09.conf @@ -0,0 +1,6 @@ +# recursion is bad + +Use foo + + +Use foo diff --git a/modules/core/test/conf/test10.conf b/modules/core/test/conf/test10.conf new file mode 100644 index 0000000..157129d --- /dev/null +++ b/modules/core/test/conf/test10.conf @@ -0,0 +1,10 @@ +# indirect recursion is bad + +Use bla + + + +Use foo + + +Use foo diff --git a/modules/core/test/conf/test11.conf b/modules/core/test/conf/test11.conf new file mode 100644 index 0000000..f397ec6 --- /dev/null +++ b/modules/core/test/conf/test11.conf @@ -0,0 +1,15 @@ +# inner macros... + + +Warning "macro $arg.in line 1" + + + +# generate a one.in macro +Use foo one + +# use it! +Use one.in + +# end processing +Error "done line 15." diff --git a/modules/core/test/conf/test12.conf b/modules/core/test/conf/test12.conf new file mode 100644 index 0000000..84403c6 --- /dev/null +++ b/modules/core/test/conf/test12.conf @@ -0,0 +1,12 @@ +# multiply defined generates a warning + + Warning "macro foo 1, line 1" + + + + Warning "macro foo 2, line 1" + + +Use foo + +Error "done line 12." diff --git a/modules/core/test/conf/test13.conf b/modules/core/test/conf/test13.conf new file mode 100644 index 0000000..244470d --- /dev/null +++ b/modules/core/test/conf/test13.conf @@ -0,0 +1,18 @@ +# case insensitive + + Warning "macro FOO line 1" + + + + Warning "macro bla line 1" + + +use foo + + + Warning "redefined macro foo line 1" + + +use FOO + +Error "done line 18." diff --git a/modules/core/test/conf/test14.conf b/modules/core/test/conf/test14.conf new file mode 100644 index 0000000..48d8888 --- /dev/null +++ b/modules/core/test/conf/test14.conf @@ -0,0 +1,23 @@ +# VirtualHost example + + + Listen $port + + DocumentRoot $dir + + Warning "directory $dir" + + # limit access to intranet subdir. + + Warning "directory $dir/intranet" + + + + +Use MyVirtualHost www.apache.org 80 /projects/apache/web + +Use MyVirtualHost www.perl.com 8080 /projects/perl/web + +Use MyVirtualHost www.ensmp.fr 1234 /projects/mines/web + +Error "done line 23." diff --git a/modules/core/test/conf/test15.conf b/modules/core/test/conf/test15.conf new file mode 100644 index 0000000..7990e15 --- /dev/null +++ b/modules/core/test/conf/test15.conf @@ -0,0 +1,9 @@ +# non nested... + + + + +use test + + +Error should not reach this point. diff --git a/modules/core/test/conf/test16.conf b/modules/core/test/conf/test16.conf new file mode 100644 index 0000000..471f66e --- /dev/null +++ b/modules/core/test/conf/test16.conf @@ -0,0 +1,11 @@ +# bad nesting + + + + + + +Use foo + + +stop diff --git a/modules/core/test/conf/test17.conf b/modules/core/test/conf/test17.conf new file mode 100644 index 0000000..f6294bb --- /dev/null +++ b/modules/core/test/conf/test17.conf @@ -0,0 +1,10 @@ +# bad but good nesting + + + + + + +Use foo + +Error "done on line 10." diff --git a/modules/core/test/conf/test18.conf b/modules/core/test/conf/test18.conf new file mode 100644 index 0000000..118617d --- /dev/null +++ b/modules/core/test/conf/test18.conf @@ -0,0 +1,10 @@ +# bad but good nesting + + + + + + +Use foo + +Error "done on line 10." diff --git a/modules/core/test/conf/test19.conf b/modules/core/test/conf/test19.conf new file mode 100644 index 0000000..6568e96 --- /dev/null +++ b/modules/core/test/conf/test19.conf @@ -0,0 +1,26 @@ +# okay till done + + + # something + Warning "macro foo line 2 in $where" + + + + Use foo Directory + + + + Use foo Location + + + + Use foo VirtualHost + + + + + Use foo "VirtualHost & Directory" + + + +Error "done line 26." diff --git a/modules/core/test/conf/test20.conf b/modules/core/test/conf/test20.conf new file mode 100644 index 0000000..ccbae0d --- /dev/null +++ b/modules/core/test/conf/test20.conf @@ -0,0 +1,11 @@ +# directory in directory through a macro + + + + Warning "macro foo $dir" + + + + + Use foo /tmp + diff --git a/modules/core/test/conf/test21.conf b/modules/core/test/conf/test21.conf new file mode 100644 index 0000000..7a8c4c9 --- /dev/null +++ b/modules/core/test/conf/test21.conf @@ -0,0 +1,11 @@ +# raise an error + + + + Error "macro foo dir /tmp" + + + + + Use foo + diff --git a/modules/core/test/conf/test22.conf b/modules/core/test/conf/test22.conf new file mode 100644 index 0000000..5a89f83 --- /dev/null +++ b/modules/core/test/conf/test22.conf @@ -0,0 +1,11 @@ +# simple nesting + + + + Warning "macro foo" + + + +Use foo + +Error "done on line 11." diff --git a/modules/core/test/conf/test23.conf b/modules/core/test/conf/test23.conf new file mode 100644 index 0000000..e21e2ee --- /dev/null +++ b/modules/core/test/conf/test23.conf @@ -0,0 +1,15 @@ +# macro defined in a directory + + + + Warning "macro foo in /tmp" + + + +Use foo + + + Use foo + + +Error "done!" diff --git a/modules/core/test/conf/test24.conf b/modules/core/test/conf/test24.conf new file mode 100644 index 0000000..d35070e --- /dev/null +++ b/modules/core/test/conf/test24.conf @@ -0,0 +1,23 @@ +# nesting... + + + + Warning "macro bla intra" + + + Warning "macro bla private" + + + +# ok location in config +Use bla + +# ok, location in VH + + Use bla + + + + # fails: Location within an Directory + Use bla + diff --git a/modules/core/test/conf/test25.conf b/modules/core/test/conf/test25.conf new file mode 100644 index 0000000..724cf94 --- /dev/null +++ b/modules/core/test/conf/test25.conf @@ -0,0 +1,27 @@ +# ok till stop. + + + Warning "restricted access policy $ips" + + + + Use RestrictedAccessPolicy 10.0.0.0/8 + + + + Use RestrictedAccessPolicy 10.0.0.0/8 + + + + Use RestrictedAccessPolicy "192.54.172.0/24 192.54.148.0/24 10.0.0.0/8" + + + + Use LocalAccessOnly + + + + Use LocalAccessOnly + + +Error "done line 27." diff --git a/modules/core/test/conf/test26.conf b/modules/core/test/conf/test26.conf new file mode 100644 index 0000000..bb4b5ad --- /dev/null +++ b/modules/core/test/conf/test26.conf @@ -0,0 +1,19 @@ +# ok till stop. +# test quotes... + + + + Warning "funny directory" + + + Warning "funny location" + + + +Use funny /unexpected/1 /intra + + + Use funny /unexpected/2 /intranet + + +Error "done!" diff --git a/modules/core/test/conf/test27.conf b/modules/core/test/conf/test27.conf new file mode 100644 index 0000000..2f3e83c --- /dev/null +++ b/modules/core/test/conf/test27.conf @@ -0,0 +1,22 @@ +# define a macro in a macro. + + + + + Warning "foo.$name $dir" + + + + +Use foo /unexpected/1 one +Use foo /unexpected/2 two + +Use foo.one +Use foo.two +Use foo.one + +UndefMacro foo.one +UndefMacro foo.two +UndefMacro foo + +Error "done!" diff --git a/modules/core/test/conf/test28.conf b/modules/core/test/conf/test28.conf new file mode 100644 index 0000000..69c1c9b --- /dev/null +++ b/modules/core/test/conf/test28.conf @@ -0,0 +1,13 @@ +# interaction with IfModule + + + + Warning "macro foo" + + + Use foo + + Error "done!" + + +Error "should not get there" diff --git a/modules/core/test/conf/test29.conf b/modules/core/test/conf/test29.conf new file mode 100644 index 0000000..7d1f380 --- /dev/null +++ b/modules/core/test/conf/test29.conf @@ -0,0 +1,10 @@ +# trigger line overflow during expansion + + + Warning aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + +Use toobigaline "cette ligne va etre vraiment trop longue ya pas de doute" + +Error "should not get there!" diff --git a/modules/core/test/conf/test30.conf b/modules/core/test/conf/test30.conf new file mode 100644 index 0000000..72b2bb2 --- /dev/null +++ b/modules/core/test/conf/test30.conf @@ -0,0 +1,12 @@ +# name conficts: the longest is chosen +# also test a parametric section + + + <$directive $dir> + Warning "section $directive $dir" + + + +Use foo /unexpected/1 Directory + +Error "done!" diff --git a/modules/core/test/conf/test31.conf b/modules/core/test/conf/test31.conf new file mode 100644 index 0000000..14964ba --- /dev/null +++ b/modules/core/test/conf/test31.conf @@ -0,0 +1,16 @@ +# parameter name conflicts + + + Warning "argument name conflicts" + $d $di $dir $dd + + +Use bla '' '' 8080 Listen + + + Warning "conflicts, but arguments are not used" + + +Use foo '' '' 8080 Listen + +Error "done on line 16." diff --git a/modules/core/test/conf/test32.conf b/modules/core/test/conf/test32.conf new file mode 100644 index 0000000..0b116ec --- /dev/null +++ b/modules/core/test/conf/test32.conf @@ -0,0 +1,7 @@ +# error if same argument name. + + +# bad + + + diff --git a/modules/core/test/conf/test33.conf b/modules/core/test/conf/test33.conf new file mode 100644 index 0000000..2a8a6db --- /dev/null +++ b/modules/core/test/conf/test33.conf @@ -0,0 +1,3 @@ +# empty name. + +Use '' diff --git a/modules/core/test/conf/test34.conf b/modules/core/test/conf/test34.conf new file mode 100644 index 0000000..1f4671f --- /dev/null +++ b/modules/core/test/conf/test34.conf @@ -0,0 +1,14 @@ +# macro parameter prefix conflicts in two orders + + + Warning "macro foo conflict one" + + + + Warning "macro bla conflict two" + + +Use foo 1 2 +Use bla 1 2 + +Error "done on line 14." diff --git a/modules/core/test/conf/test35.conf b/modules/core/test/conf/test35.conf new file mode 100644 index 0000000..37a623e --- /dev/null +++ b/modules/core/test/conf/test35.conf @@ -0,0 +1,10 @@ +# unused arguments + + + Warning "macro cannot be used just within a comment u1 u2 u3" + # n1 n2 + + +Use warnings 1 2 3 4 5 + +Error "done on line 10." diff --git a/modules/core/test/conf/test36.conf b/modules/core/test/conf/test36.conf new file mode 100644 index 0000000..a68667e --- /dev/null +++ b/modules/core/test/conf/test36.conf @@ -0,0 +1,12 @@ + + Warning "many warnings! $u $u1 $u2" + # $n $n1 $n2 + + +# warn about unused arguments +Use warnings 1 2 3 4 5 6 + +# may warn about empty arguments? +Use warnings '' '' '' '' '' '' + +Error "done!" diff --git a/modules/core/test/conf/test37.conf b/modules/core/test/conf/test37.conf new file mode 100644 index 0000000..296dde7 --- /dev/null +++ b/modules/core/test/conf/test37.conf @@ -0,0 +1,7 @@ +# empty argument name + + + Warn "macro stupid" + + +Use stupid hello diff --git a/modules/core/test/conf/test38.conf b/modules/core/test/conf/test38.conf new file mode 100644 index 0000000..184763f --- /dev/null +++ b/modules/core/test/conf/test38.conf @@ -0,0 +1,10 @@ +# ifmodule + + +Warning it is really a good idea to have mod_macro.c installed. + + + +Error it seems you do not have mod perl installed. + + diff --git a/modules/core/test/conf/test39.conf b/modules/core/test/conf/test39.conf new file mode 100644 index 0000000..792232f --- /dev/null +++ b/modules/core/test/conf/test39.conf @@ -0,0 +1,23 @@ +# okay till stop. + + + + Warning Thanks for using mod_macro! + + + + + + Error Sorry, mod_macro must be installed to run this configuration file. + + + +Use ModMacro + + + Warning "macro foo" + + +Use foo + +Error "done!" diff --git a/modules/core/test/conf/test40.conf b/modules/core/test/conf/test40.conf new file mode 100644 index 0000000..e6b81f7 --- /dev/null +++ b/modules/core/test/conf/test40.conf @@ -0,0 +1,33 @@ +# configuration example with mod_macro +# + + + DocumentRoot /foo/document/root/directory + + + # access control to subdirs... + + Warning "location /$subdir" + + + + # repeat uses + Use SubDirAccessControl A + Use SubDirAccessControl B + Use SubDirAccessControl C + Use SubDirAccessControl D + Use SubDirAccessControl E + Use SubDirAccessControl G + Use SubDirAccessControl H + Use SubDirAccessControl J + Use SubDirAccessControl K + Use SubDirAccessControl L + Use SubDirAccessControl M + Use SubDirAccessControl N + + # cleanup + UndefMacro SubDirAccessControl + + + +Error Stop configuration file processing. diff --git a/modules/core/test/conf/test41.conf b/modules/core/test/conf/test41.conf new file mode 100644 index 0000000..c4e6bdb --- /dev/null +++ b/modules/core/test/conf/test41.conf @@ -0,0 +1,20 @@ +# another configuration example without mod_macro + + + DocumentRoot /foo/document/root/directory + + + Warning "location /A" + + + + Warning "location /B" + + + + Warning "location /C" + + + + +Error Stop configuration file processing. diff --git a/modules/core/test/conf/test42.conf b/modules/core/test/conf/test42.conf new file mode 100644 index 0000000..a142604 --- /dev/null +++ b/modules/core/test/conf/test42.conf @@ -0,0 +1,13 @@ +# multiple macro uses + + + Warning "macro foo $p" + + +Use foo '' +Use foo '' +Use foo '' +Use foo '' +Use foo '' + +Error "done on line 13." diff --git a/modules/core/test/conf/test43.conf b/modules/core/test/conf/test43.conf new file mode 100644 index 0000000..264b916 --- /dev/null +++ b/modules/core/test/conf/test43.conf @@ -0,0 +1,29 @@ +# non necessarily nested. + + + +# hello + + + + + + +Use begindir /unexpected/1 +Use enddir + + +Use begindir /unexpected/2 +Use enddir + +Use begindir /unexpected/3 + + +Use enddir + + +Use begindir /unexpected/4 +Use enddir + + +Error ok! diff --git a/modules/core/test/conf/test44.conf b/modules/core/test/conf/test44.conf new file mode 100644 index 0000000..ef4883e --- /dev/null +++ b/modules/core/test/conf/test44.conf @@ -0,0 +1,19 @@ +# working recursion... + + +use bla + + + + +use foo + + + + + +# foo gonna call bla, bla wont call foo back... +use foo + + +Error okay. diff --git a/modules/core/test/conf/test45.conf b/modules/core/test/conf/test45.conf new file mode 100644 index 0000000..0394935 --- /dev/null +++ b/modules/core/test/conf/test45.conf @@ -0,0 +1,7 @@ +# strange chars + + +# hello $1 %2 &3 @4 #5 ~6 *7 .8 ,9 !a -b +c =d :e ;f ?g + + +Error "done on line 7." diff --git a/modules/core/test/conf/test46.conf b/modules/core/test/conf/test46.conf new file mode 100644 index 0000000..50520ed --- /dev/null +++ b/modules/core/test/conf/test46.conf @@ -0,0 +1,11 @@ +# various working prefixes + + +# hello %j @k + + + +# not used. + + +Error okay. diff --git a/modules/core/test/conf/test47.conf b/modules/core/test/conf/test47.conf new file mode 100644 index 0000000..6e73664 --- /dev/null +++ b/modules/core/test/conf/test47.conf @@ -0,0 +1,15 @@ +# empty macro contents... + + + + +Use foo + + + + + +# some contents... + + +Error okay. diff --git a/modules/core/test/conf/test48.conf b/modules/core/test/conf/test48.conf new file mode 100644 index 0000000..96bf461 --- /dev/null +++ b/modules/core/test/conf/test48.conf @@ -0,0 +1,23 @@ +# test substitution... + + +Warning %premier + + +Use M 1 +Use M 12 +Use M 123 +Use M 1234 +Use M 12345 +Use M 123456 +Use M 1234567 +Use M 12345678 +Use M 123456789 +Use M 1234567890 +Use M 1234567890a +Use M 1234567890ab +Use M 1234567890abc +Use M 1234567890abcd +Use M 1234567890abcde + +Error "done line 23." diff --git a/modules/core/test/conf/test49.conf b/modules/core/test/conf/test49.conf new file mode 100644 index 0000000..7a21c82 --- /dev/null +++ b/modules/core/test/conf/test49.conf @@ -0,0 +1,2 @@ +# undef macro before anything +UndefMacro foo diff --git a/modules/core/test/conf/test50.conf b/modules/core/test/conf/test50.conf new file mode 100644 index 0000000..33dd359 --- /dev/null +++ b/modules/core/test/conf/test50.conf @@ -0,0 +1,5 @@ +# undef non existing macro + + Warning "foo macro" + +UndefMacro bla diff --git a/modules/core/test/conf/test51.conf b/modules/core/test/conf/test51.conf new file mode 100644 index 0000000..50214fa --- /dev/null +++ b/modules/core/test/conf/test51.conf @@ -0,0 +1,9 @@ +# undef existing macro, and try to use it + + Warning "foo macro contents" + +# expanded, but will not be processed because of error +Use foo +UndefMacro foo +# error, does not exist anymore +Use foo diff --git a/modules/core/test/conf/test52.conf b/modules/core/test/conf/test52.conf new file mode 100644 index 0000000..bb77c73 --- /dev/null +++ b/modules/core/test/conf/test52.conf @@ -0,0 +1,8 @@ +# undef existing macro, and try to use it + + Warning "foo macro contents line 1" + +Use foo +UndefMacro foo + +Error "done line 8." diff --git a/modules/core/test/conf/test53.conf b/modules/core/test/conf/test53.conf new file mode 100644 index 0000000..08e8c98 --- /dev/null +++ b/modules/core/test/conf/test53.conf @@ -0,0 +1,2 @@ +# use undefined macro without prior definition +Use bla diff --git a/modules/core/test/conf/test54.conf b/modules/core/test/conf/test54.conf new file mode 100644 index 0000000..7dd30ac --- /dev/null +++ b/modules/core/test/conf/test54.conf @@ -0,0 +1,6 @@ +# empty macro + + +Use foo + +Error "done line 6." diff --git a/modules/core/test/conf/test55.conf b/modules/core/test/conf/test55.conf new file mode 100644 index 0000000..bd978e9 --- /dev/null +++ b/modules/core/test/conf/test55.conf @@ -0,0 +1,11 @@ +# line numbers... + + Warning "macro foo(:2) line 1 ($where)" + + + Warning "macro bla(:5) line 1 ($where)" + Use foo "bla line 2" + +Use foo "file line 9" +Use bla "file line 10" +Error "done line 11." diff --git a/modules/core/test/conf/test56.conf b/modules/core/test/conf/test56.conf new file mode 100644 index 0000000..b7366a2 --- /dev/null +++ b/modules/core/test/conf/test56.conf @@ -0,0 +1,18 @@ +# nesting warnings + + + Warning "Open:2 $dir" + + + Warning "Close:1" + + + +# some uses +Use Open /tmp +Use Close + +Use Open /etc +Use Close + +Error "done line 18." diff --git a/modules/core/test/conf/test57.conf b/modules/core/test/conf/test57.conf new file mode 100644 index 0000000..7c36868 --- /dev/null +++ b/modules/core/test/conf/test57.conf @@ -0,0 +1,4 @@ +# empty argument name + + Warning "macro foo line 1" + diff --git a/modules/core/test/conf/test58.conf b/modules/core/test/conf/test58.conf new file mode 100644 index 0000000..6c8a2eb --- /dev/null +++ b/modules/core/test/conf/test58.conf @@ -0,0 +1,4 @@ +# bad directive closing + diff --git a/modules/core/test/conf/test59.conf b/modules/core/test/conf/test59.conf new file mode 100644 index 0000000..9f43d7d --- /dev/null +++ b/modules/core/test/conf/test59.conf @@ -0,0 +1,4 @@ +# empty name + + Warning "empty quoted name macro" + diff --git a/modules/core/test/conf/test60.conf b/modules/core/test/conf/test60.conf new file mode 100644 index 0000000..969a4eb --- /dev/null +++ b/modules/core/test/conf/test60.conf @@ -0,0 +1,17 @@ +# @ escaping + + Warning "macro Foo arg 1: $one" + Warning "macro Foo arg 2: $two" + + + Warning Macro Bla arg 1: @first + Warning Macro Bla arg 2: @second + Use Foo @first 'second' + Use Foo 'first' @second + Use Foo @first @second + + +Use Foo hello world +Use Bla "hello world" "thank you" + +Error "done on line 17." diff --git a/modules/core/test/conf/test61.conf b/modules/core/test/conf/test61.conf new file mode 100644 index 0000000..cd28597 --- /dev/null +++ b/modules/core/test/conf/test61.conf @@ -0,0 +1,18 @@ +# deep expansion + + Warning "F1:1 x=$x" + + + Warning "F2:1 x=$x" + Use F1 $x + + + Warning "F3:1 x=$x" + Use F2 $x + + + Warning "F4:1 x=$x" + Use F3 $x + +Use F4 "line=17" +Error "done line 18." diff --git a/modules/core/test/conf/test62.conf b/modules/core/test/conf/test62.conf new file mode 100644 index 0000000..9d611de --- /dev/null +++ b/modules/core/test/conf/test62.conf @@ -0,0 +1,25 @@ +# test continuations + + Warning \ + "Line:1-2 start at $start" + Warning \ + "Line:3-4 stop at $stop" + + +Use Line 11 11 +Use Line \ + 12 13 +Use Line \ + 14 \ + 16 +Use Line 17 \ + 18 +Use Line \ + \ + 19 \ + \ + 23 + +Error "done line 25." diff --git a/modules/core/test/conf/test63.conf b/modules/core/test/conf/test63.conf new file mode 100644 index 0000000..7988ae4 --- /dev/null +++ b/modules/core/test/conf/test63.conf @@ -0,0 +1,9 @@ +# include +include ${PWD}/inc63_1.conf +Use Foo "test63.conf:3" + + Warning "Bla at $where" + +include ${PWD}/inc63_2.conf +Use Bla "test63.conf:8" +Error "done at line 9." diff --git a/modules/core/test/conf/test64.conf b/modules/core/test/conf/test64.conf new file mode 100644 index 0000000..6c12328 --- /dev/null +++ b/modules/core/test/conf/test64.conf @@ -0,0 +1,5 @@ +# just continuations +Warning "on line 2" +Warning \ + "from line 3 to line 4" +Error "done on line 5." diff --git a/modules/core/test/conf/test65.conf b/modules/core/test/conf/test65.conf new file mode 100644 index 0000000..df9adc3 --- /dev/null +++ b/modules/core/test/conf/test65.conf @@ -0,0 +1,11 @@ +# simple use continuation + + # first macro line is a comment + Warning "Line: $line" + +Use Line \ + "on line 6-7" +Use \ + Line \ + "on line 8-10" +Error "done on line 11." diff --git a/modules/core/test/conf/test66.conf b/modules/core/test/conf/test66.conf new file mode 100644 index 0000000..a14e587 --- /dev/null +++ b/modules/core/test/conf/test66.conf @@ -0,0 +1,7 @@ +# no double substitution + + Warning "Foo: x=$x y=$y" + +Use Foo X Y +Use Foo "$y" "$x" +Error "done on line 7." diff --git a/modules/core/test/conf/test67.conf b/modules/core/test/conf/test67.conf new file mode 100644 index 0000000..04a5d3d --- /dev/null +++ b/modules/core/test/conf/test67.conf @@ -0,0 +1 @@ +Error "done at line 1 without LF." \ No newline at end of file diff --git a/modules/core/test/conf/test68.conf b/modules/core/test/conf/test68.conf new file mode 100644 index 0000000..2a7b85b --- /dev/null +++ b/modules/core/test/conf/test68.conf @@ -0,0 +1,5 @@ +# two directives with continuations & no eol at eof +Warning \ + "line 2-3" +Error \ + "done on line 4-5." \ No newline at end of file diff --git a/modules/core/test/conf/test69.conf b/modules/core/test/conf/test69.conf new file mode 100644 index 0000000..11a0830 --- /dev/null +++ b/modules/core/test/conf/test69.conf @@ -0,0 +1,14 @@ +# warn if ignored non-blank stuff after closing '>' + this stuff is ignored... + Warning "Foo" + this stuff is ignored as well... +Use Foo + + Warning "Bla" + +Use Bla + # comments are fine + Warning "Comments" + # comments are fine +Use Comments +Error "done on line 14." diff --git a/modules/core/test/ref/test01.out b/modules/core/test/ref/test01.out new file mode 100644 index 0000000..9ea6665 --- /dev/null +++ b/modules/core/test/ref/test01.out @@ -0,0 +1,3 @@ +# testing with conf/test01.conf +httpd: Syntax error on line 2 of ./conf/test01.conf: +# exit: 1 diff --git a/modules/core/test/ref/test08.out b/modules/core/test/ref/test08.out new file mode 100644 index 0000000..124c7a0 --- /dev/null +++ b/modules/core/test/ref/test08.out @@ -0,0 +1,3 @@ +# testing with conf/test08.conf +httpd: Syntax error on line 3 of ./conf/test08.conf: without matching section +# exit: 1 diff --git a/modules/core/test/ref/test09.out b/modules/core/test/ref/test09.out new file mode 100644 index 0000000..9af1225 --- /dev/null +++ b/modules/core/test/ref/test09.out @@ -0,0 +1,3 @@ +# testing with conf/test09.conf +httpd: Syntax error on line 1 of macro 'foo' (defined on line 2 of "./conf/test09.conf") used on line 6 of "./conf/test09.conf": recursive use of macro 'foo' is invalid +# exit: 1 diff --git a/modules/core/test/ref/test10.out b/modules/core/test/ref/test10.out new file mode 100644 index 0000000..4d81abc --- /dev/null +++ b/modules/core/test/ref/test10.out @@ -0,0 +1,3 @@ +# testing with conf/test10.conf +httpd: Syntax error on line 1 of macro 'bla' (defined on line 6 of "./conf/test10.conf") used on line 1 of "macro 'foo' (defined on line 2 of "./conf/test10.conf") used on line 10 of "./conf/test10.conf"": recursive use of macro 'foo' is invalid +# exit: 1 diff --git a/modules/core/test/ref/test11.out b/modules/core/test/ref/test11.out new file mode 100644 index 0000000..d18c95e --- /dev/null +++ b/modules/core/test/ref/test11.out @@ -0,0 +1,6 @@ +# testing with conf/test11.conf +[core:warn] macro one.in line 1 on line 1 of macro 'one.in' (defined on line 1 of "macro 'foo' (defined on line 2 of "./conf/test11.conf") used on line 9 of "./conf/test11.conf"") used on line 12 of "./conf/test11.conf" +[core:error] done line 15. on line 15 of ./conf/test11.conf +AH00526: Syntax error on line 15 of ./conf/test11.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test12.out b/modules/core/test/ref/test12.out new file mode 100644 index 0000000..b1ab234 --- /dev/null +++ b/modules/core/test/ref/test12.out @@ -0,0 +1,7 @@ +# testing with conf/test12.conf +[macro:warn] macro 'foo' multiply defined: defined on line 2 of "./conf/test12.conf", redefined on line 6 of "./conf/test12.conf" +[core:warn] macro foo 2, line 1 on line 1 of macro 'foo' (defined on line 6 of "./conf/test12.conf") used on line 10 of "./conf/test12.conf" +[core:error] done line 12. on line 12 of ./conf/test12.conf +AH00526: Syntax error on line 12 of ./conf/test12.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test13.out b/modules/core/test/ref/test13.out new file mode 100644 index 0000000..13d501e --- /dev/null +++ b/modules/core/test/ref/test13.out @@ -0,0 +1,8 @@ +# testing with conf/test13.conf +[macro:warn] macro 'foo' multiply defined: defined on line 2 of "./conf/test13.conf", redefined on line 12 of "./conf/test13.conf" +[core:warn] macro FOO line 1 on line 1 of macro 'foo' (defined on line 2 of "./conf/test13.conf") used on line 10 of "./conf/test13.conf" +[core:warn] redefined macro foo line 1 on line 1 of macro 'foo' (defined on line 12 of "./conf/test13.conf") used on line 16 of "./conf/test13.conf" +[core:error] done line 18. on line 18 of ./conf/test13.conf +AH00526: Syntax error on line 18 of ./conf/test13.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test14.out b/modules/core/test/ref/test14.out new file mode 100644 index 0000000..1650715 --- /dev/null +++ b/modules/core/test/ref/test14.out @@ -0,0 +1,14 @@ +# testing with conf/test14.conf +AH00112: Warning: DocumentRoot [/projects/apache/web] does not exist +[core:warn] directory /projects/apache/web on line 5 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 17 of "./conf/test14.conf" +[core:warn] directory /projects/apache/web/intranet on line 8 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 17 of "./conf/test14.conf" +AH00112: Warning: DocumentRoot [/projects/perl/web] does not exist +[core:warn] directory /projects/perl/web on line 5 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 19 of "./conf/test14.conf" +[core:warn] directory /projects/perl/web/intranet on line 8 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 19 of "./conf/test14.conf" +AH00112: Warning: DocumentRoot [/projects/mines/web] does not exist +[core:warn] directory /projects/mines/web on line 5 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 21 of "./conf/test14.conf" +[core:warn] directory /projects/mines/web/intranet on line 8 of macro 'myvirtualhost' (defined on line 3 of "./conf/test14.conf") used on line 21 of "./conf/test14.conf" +[core:error] done line 23. on line 23 of ./conf/test14.conf +AH00526: Syntax error on line 23 of ./conf/test14.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test15.out b/modules/core/test/ref/test15.out new file mode 100644 index 0000000..b0b82b7 --- /dev/null +++ b/modules/core/test/ref/test15.out @@ -0,0 +1,6 @@ +# testing with conf/test15.conf +[macro:warn] bad cumulated nesting (+1) in macro 'test' (defined on line 2 of "./conf/test15.conf") +[core:error] should not reach this point. on line 9 of ./conf/test15.conf +AH00526: Syntax error on line 9 of ./conf/test15.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test16.out b/modules/core/test/ref/test16.out new file mode 100644 index 0000000..6e0f9ca --- /dev/null +++ b/modules/core/test/ref/test16.out @@ -0,0 +1,5 @@ +# testing with conf/test16.conf +[macro:warn] bad (negative) nesting on line 2 of macro 'foo' (defined on line 3 of "./conf/test16.conf") +[macro:warn] bad cumulated nesting (-1) in macro 'foo' (defined on line 3 of "./conf/test16.conf") +httpd: Syntax error on line 9 of ./conf/test16.conf: without matching section +# exit: 1 diff --git a/modules/core/test/ref/test17.out b/modules/core/test/ref/test17.out new file mode 100644 index 0000000..c6ca16d --- /dev/null +++ b/modules/core/test/ref/test17.out @@ -0,0 +1,7 @@ +# testing with conf/test17.conf +[macro:warn] bad (negative) nesting on line 2 of macro 'foo' (defined on line 3 of "./conf/test17.conf") +[macro:warn] bad cumulated nesting (-1) in macro 'foo' (defined on line 3 of "./conf/test17.conf") +[core:error] done on line 10. on line 10 of ./conf/test17.conf +AH00526: Syntax error on line 10 of ./conf/test17.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test18.out b/modules/core/test/ref/test18.out new file mode 100644 index 0000000..c5cee81 --- /dev/null +++ b/modules/core/test/ref/test18.out @@ -0,0 +1,7 @@ +# testing with conf/test18.conf +[macro:warn] bad (negative) nesting on line 2 of macro 'foo' (defined on line 3 of "./conf/test18.conf") +[macro:warn] bad cumulated nesting (-1) in macro 'foo' (defined on line 3 of "./conf/test18.conf") +[core:error] done on line 10. on line 10 of ./conf/test18.conf +AH00526: Syntax error on line 10 of ./conf/test18.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test19.out b/modules/core/test/ref/test19.out new file mode 100644 index 0000000..411e569 --- /dev/null +++ b/modules/core/test/ref/test19.out @@ -0,0 +1,9 @@ +# testing with conf/test19.conf +[core:warn] macro foo line 2 in Directory on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 9 of "./conf/test19.conf" +[core:warn] macro foo line 2 in Location on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 13 of "./conf/test19.conf" +[core:warn] macro foo line 2 in VirtualHost on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 17 of "./conf/test19.conf" +[core:warn] macro foo line 2 in VirtualHost & Directory on line 1 of macro 'foo' (defined on line 3 of "./conf/test19.conf") used on line 22 of "./conf/test19.conf" +[core:error] done line 26. on line 26 of ./conf/test19.conf +AH00526: Syntax error on line 26 of ./conf/test19.conf: +Configuration processing stopped by Error directive +# exit: 1 diff --git a/modules/core/test/ref/test20.out b/modules/core/test/ref/test20.out new file mode 100644 index 0000000..3ce2b60 --- /dev/null +++ b/modules/core/test/ref/test20.out @@ -0,0 +1,4 @@ +# testing with conf/test20.conf +AH00526: Syntax error on line 1 of macro 'foo' (defined on line 3 of "./conf/test20.conf") used on line 10 of "./conf/test20.conf": + directive missing closing '>' +# exit: 1 diff --git a/modules/core/test/ref/test59.out b/modules/core/test/ref/test59.out new file mode 100644 index 0000000..7895917 --- /dev/null +++ b/modules/core/test/ref/test59.out @@ -0,0 +1,3 @@ +# testing with conf/test59.conf +httpd: Syntax error on line 2 of ./conf/test59.conf: ' on line 2 of ./conf/test69.conf: this stuff is ignored... +[macro:warn] non blank chars found after directive closing on line 4 of ./conf/test69.conf: this stuff is ignored as well... +[core:warn] Foo on line 1 of macro 'foo' (defined on line 2 of "./conf/test69.conf") used on line 5 of "./conf/test69.conf" +[core:warn] Bla on line 1 of macro 'bla' (defined on line 6 of "./conf/test69.conf") used on line 9 of "./conf/test69.conf" +[core:warn] Comments on line 1 of macro 'comments' (defined on line 10 of "./conf/test69.conf") used on line 13 of "./conf/test69.conf" +[core:error] done on line 14. on line 14 of ./conf/test69.conf +AH00526: Syntax error on line 14 of ./conf/test69.conf: +Configuration processing stopped by Error directive +# exit: 1 -- cgit v1.2.3